Quantcast
Channel: ASP.NET MVC / Web API / Web Pages
Viewing all 7925 articles
Browse latest View live

Updated Wiki: CORS support for ASP.NET Web API

$
0
0

CORS support for ASP.NET Web API

Overview

Cross-origin resource sharing (CORS) is a standard that allows web pages to make AJAX requests to another domain. It relaxes the same-origin policy implemented on the web browsers that limits the calls to be within the same domain.

The CORS spec (http://www.w3.org/TR/cors/) defines the way how the server and browser interact in order to make cross origin calls. Most of the modern browsers today already support CORS. Our goal is to enable the support for our Web API services.

Scenarios

Enabling CORS

We’ve added a new extension method to the HttpConfiguration to enable CORS. With this, you can enable the support globally, per controller or per action.

Globally

You can define a global setting when calling EnableCors. For example, the following will enable CORS globally, allowing all origins, methods, and headers. There’re many settings on the EnableCorsAttribute that you can configure which we will see later.

using System.Web.Http.Cors;
publicstaticclass WebApiConfig
{
    publicstaticvoid Register(HttpConfiguration config)
    {
        // other settings removed for clarity

        config.EnableCors(new EnableCorsAttribute());
    }
}

Per Controller

The support can also be scoped to the controller. First you just need to call EnableCors without providing a global setting.

using System.Web.Http.Cors;
publicstaticclass WebApiConfig
{
    publicstaticvoid Register(HttpConfiguration config)
    {
        // other settings removed for clarity

        config.EnableCors();
    }
}

Then you can declare the EnableCorsAttribute on the controller to enable CORS.

[EnableCors]
publicclass ValuesController : ApiController
{
    public IEnumerable<string> Get()
    {
        returnnewstring[] { "value1", "value2" };
    }

    publicstring Get(int id)
    {
        return"value "+ id;
    }
}

Per Action

In a similar fashion, you can enable CORS on a single action by first calling EnableCors.

using System.Web.Http.Cors;
publicstaticclass WebApiConfig
{
    publicstaticvoid Register(HttpConfiguration config)
    {
        // other settings removed for clarity

        config.EnableCors();
    }
}

And then declare the EnableCorsAttribute on an action.

publicclass ValuesController : ApiController
{
    public IEnumerable<string> Get()
    {
        returnnewstring[] { "value1", "value2" };
    }

    [EnableCors]
    publicstring Get(int id)
    {
        return"value "+ id;
    }
}

Attribute precedence

When you have the EnableCorsAttribute applied on all scopes (globally, per-controller, per-action), the closest one to the resource wins. Therefore the precedence is defined as follows:

  1. Action
  2. Controller
  3. Global

Excluding a controller or an action from EnableCors

You can use [DisableCors] attribute to exclude a controller or and action from the global or per-controller settings. For example, the following will enable CORS for all the actions in the ValuesController except for Get(int id).

[EnableCors]
publicclass ValuesController : ApiController
{
    public IEnumerable<string> Get()
    {
        returnnewstring[] { "value1", "value2" };
    }

    [DisableCors]
    publicstring Get(int id)
    {
        return"value "+ id;
    }
}

Configuring [EnableCors] attribute

There’re few settings under the EnableCorsAttribute. These settings are defined by the CORS spec (http://www.w3.org/TR/cors/#resource-processing-model).

  • Origins
  • Headers
  • Methods
  • ExposedHeaders
  • SupportsCredentials
  • PreflightMaxAge

By default, EnableCorsAttribute will allow all origins, methods and headers. Note that when you declare the attribute on an action it automatically assumes the HTTP Method of the action that you declared on.

As soon as you specify the origins, you are basically limiting the access to the specified origins. The same applies to the methods and the headers.

For example, the following will only allow “http://localhost” and “http://sample.com” to access the ValuesController from the browser though AJAX. Note that it is still allowing any methods and headers because they’re not specified.

[EnableCors(Origins = new[] { "http://localhost", "http://sample.com" })]
publicclass ValuesController : ApiController
{
    public IEnumerable<string> Get()
    {
        returnnewstring[] { "value1", "value2" };
    }

    publicstring Get(int id)
    {
        return"value "+ id;
    }
}

Implementing a custom ICorsPolicyProvider

You can implement ICorsPolicyProvider to load the CORS settings/policy dynamically from other sources such as web.config or database. In fact, both the EnableCorsAttribute and DisableCorsAttribute implement this interface internally.

namespace System.Web.Http.Cors
{
    public interface ICorsPolicyProvider
    {
        Task GetCorsPolicyAsync(HttpRequestMessage request);
    }
}

Note that the ICorsPolicyProvider is async so that we don’t block the thread on I/O.

Sample

Here is a custom implementation of ICorsPolicyProvider that loads the origins from web.config.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
publicclass EnableCorsAppSettingsAttribute : Attribute, ICorsPolicyProvider
{
    private CorsPolicy _policy;

    public EnableCorsAppSettingsAttribute(string appSettingOriginKey)
    {
        _policy = new CorsPolicy
        {
            AllowAnyMethod = true,
            AllowAnyHeader = true
        };

        // loads the origins from AppSettingsstring originsString = ConfigurationManager.AppSettings[appSettingOriginKey];
        if (!String.IsNullOrEmpty(originsString))
        {
            foreach (var origin in originsString.Split(','))
            {
                _policy.Origins.Add(origin);
            }
        }
    }

    public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request)
    {
        return Task.FromResult(_policy);
    }
}

You can apply it on the controller/action just like EnableCorsAttribute.

[EnableCorsAppSettings("internal:origins")]
publicclass ValuesController : ApiController
{
    public IEnumerable<string> Get()
    {
        returnnewstring[] { "value1", "value2" };
    }

    publicstring Get(int id)
    {
        return"value "+ id;
    }
}

And it will read the “internal:origins” appSetting from the web.config.

<appSettings><addkey="webpages:Version"value="2.0.0.0"/><addkey="webpages:Enabled"value="false"/><addkey="PreserveLoginUrl"value="true"/><addkey="ClientValidationEnabled"value="true"/><addkey="UnobtrusiveJavaScriptEnabled"value="true"/><addkey="internal:origins"value="http://example.com,http://webapisample.azurewebsites.net"/></appSettings>

Implementing a custom ICorsPolicyProviderFactory

ICorsPolicyProviderFactory is an abstraction that allows you to specify how the ICorsPolicyProvider are retrieved. By default we provide the AttributeBasedPolicyProviderFactory which allows you to specify the ICorsPolicyProvider as attributes ([EnableCors], [DisableCors]). However you can extend the ICorsPolicyProviderFactory to create a centralized configuration model.

namespace System.Web.Http.Cors
{
    publicinterface ICorsPolicyProviderFactory
    {
        ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request);
    }
}

You can register the custom ICorsPolicyProviderFactory through SetCorsPolicyProviderFactory extension method.

publicstaticclass HttpConfigurationExtensions
{
    // other extensions removed for claritypublicstaticvoid SetCorsPolicyProviderFactory(this HttpConfiguration httpConfiguration, ICorsPolicyProviderFactory corsPolicyProviderFactory);
}
Sample

Here is a custom implementation of ICorsPolicyProviderFactory that allows you to configure the CORS settings through your own CorsConfiguration class instead of attributes.

publicclass ConfigBasedPolicyProviderFactory : ICorsPolicyProviderFactory
{
    private CorsConfiguration _configuration;

    public ConfigBasedPolicyProviderFactory(CorsConfiguration configuration)
    {
        _configuration = configuration;
    }

    public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
    {
        var routeData = request.GetRouteData();
        if (routeData == null || !routeData.Values.Keys.Contains("controller"))
        {
            returnnull;
        }
        var controller = routeData.Values["controller"] asstring;
        return _configuration.GetPolicyForRequest(controller);
    }
}
publicclass CorsConfiguration
{
    private Dictionary<string, EnableCorsAttribute> _settings = 
   	new Dictionary<string, EnableCorsAttribute>();

    publicvoid AddSetting(string controller, EnableCorsAttribute policyProvider)
    {
        _settings.Add(controller, policyProvider);
    }

    publicvirtual EnableCorsAttribute GetPolicyForRequest(string controller)
    {
        EnableCorsAttribute policyProvider;
        _settings.TryGetValue(controller, out policyProvider);
        return policyProvider;
    }
}

Once the ConfigBasedPolicyProviderFactory is registered, it will enable CORS on ValuesController and UsersController.

CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.AddSetting("Values", new EnableCorsAttribute());
corsConfig.AddSetting("Users", new EnableCorsAttribute { Origins = new[] { "http://localhost" } });
config.SetCorsPolicyProviderFactory(new ConfigBasedPolicyProviderFactory(corsConfig));

config.EnableCors();

Updated Wiki: Specs

Updated Wiki: CORS support for ASP.NET Web API

$
0
0

CORS support for ASP.NET Web API

Overview

Cross-origin resource sharing (CORS) is a standard that allows web pages to make AJAX requests to another domain. It relaxes the same-origin policy implemented on the web browsers that limits the calls to be within the same domain.

The CORS spec (http://www.w3.org/TR/cors/) defines the way how the server and browser interact in order to make cross origin calls. Most of the modern browsers today already support CORS. Our goal is to enable the support for our Web API services.

Scenarios

Enabling CORS

We’ve added a new extension method to the HttpConfiguration to enable CORS. With this, you can enable the support globally, per controller or per action.

Globally

You can define a global setting when calling EnableCors. For example, the following will enable CORS globally, allowing all origins, methods, and headers. There’re many settings on the EnableCorsAttribute that you can configure which we will see later.

using System.Web.Http.Cors;publicstaticclass WebApiConfig
{publicstaticvoid Register(HttpConfiguration config)
    {// other settings removed for clarity

        config.EnableCors(new EnableCorsAttribute());
    }
}

Per Controller

The support can also be scoped to the controller. First you just need to call EnableCors without providing a global setting.

using System.Web.Http.Cors;publicstaticclass WebApiConfig
{publicstaticvoid Register(HttpConfiguration config)
    {// other settings removed for clarity

        config.EnableCors();
    }
}

Then you can declare the EnableCorsAttribute on the controller to enable CORS.

[EnableCors]publicclass ValuesController : ApiController
{public IEnumerable<string> Get()
    {returnnewstring[] { "value1", "value2" };
    }publicstring Get(int id)
    {return"value "+ id;
    }
}

Per Action

In a similar fashion, you can enable CORS on a single action by first calling EnableCors.

using System.Web.Http.Cors;publicstaticclass WebApiConfig
{publicstaticvoid Register(HttpConfiguration config)
    {// other settings removed for clarity

        config.EnableCors();
    }
}

And then declare the EnableCorsAttribute on an action.

publicclass ValuesController : ApiController
{public IEnumerable<string> Get()
    {returnnewstring[] { "value1", "value2" };
    }

    [EnableCors]
    publicstring Get(int id)
    {return"value "+ id;
    }
}

Attribute precedence

When you have the EnableCorsAttribute applied on all scopes (globally, per-controller, per-action), the closest one to the resource wins. Therefore the precedence is defined as follows:

  1. Action
  2. Controller
  3. Global

Excluding a controller or an action from EnableCors

You can use [DisableCors] attribute to exclude a controller or and action from the global or per-controller settings. For example, the following will enable CORS for all the actions in the ValuesController except for Get(int id).

[EnableCors]publicclass ValuesController : ApiController
{public IEnumerable<string> Get()
    {returnnewstring[] { "value1", "value2" };
    }

    [DisableCors]
    publicstring Get(int id)
    {return"value "+ id;
    }
}

Configuring [EnableCors] attribute

There’re few settings under the EnableCorsAttribute. These settings are defined by the CORS spec (http://www.w3.org/TR/cors/#resource-processing-model).

  • Origins
  • Headers
  • Methods
  • ExposedHeaders
  • SupportsCredentials
  • PreflightMaxAge

By default, EnableCorsAttribute will allow all origins, methods and headers. Note that when you declare the attribute on an action it automatically assumes the HTTP Method of the action that you declared on.

As soon as you specify the origins, you are basically limiting the access to the specified origins. The same applies to the methods and the headers.

For example, the following will only allow “http://localhost” and “http://sample.com” to access the ValuesController from the browser though AJAX. Note that it is still allowing any methods and headers because they’re not specified.

[EnableCors(Origins = new[] { "http://localhost", "http://sample.com" })]publicclass ValuesController : ApiController
{public IEnumerable<string> Get()
    {returnnewstring[] { "value1", "value2" };
    }publicstring Get(int id)
    {return"value "+ id;
    }
}

Implementing a custom ICorsPolicyProvider

You can implement ICorsPolicyProvider to load the CORS settings/policy dynamically from other sources such as web.config or database. In fact, both the EnableCorsAttribute and DisableCorsAttribute implement this interface internally.

namespace System.Web.Http.Cors
{
    public interface ICorsPolicyProvider
    {
        Task GetCorsPolicyAsync(HttpRequestMessage request);
    }
}

Note that the ICorsPolicyProvider is async so that we don’t block the thread on I/O.

Sample

Here is a custom implementation of ICorsPolicyProvider that loads the origins from web.config.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]publicclass EnableCorsAppSettingsAttribute : Attribute, ICorsPolicyProvider
{private CorsPolicy _policy;public EnableCorsAppSettingsAttribute(string appSettingOriginKey)
    {
        _policy = new CorsPolicy
        {
            AllowAnyMethod = true,
            AllowAnyHeader = true
        };// loads the origins from AppSettingsstring originsString = ConfigurationManager.AppSettings[appSettingOriginKey];if (!String.IsNullOrEmpty(originsString))
        {foreach (var origin in originsString.Split(','))
            {
                _policy.Origins.Add(origin);
            }
        }
    }public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request)
    {return Task.FromResult(_policy);
    }
}

You can apply it on the controller/action just like EnableCorsAttribute.

[EnableCorsAppSettings("internal:origins")]publicclass ValuesController : ApiController
{public IEnumerable<string> Get()
    {returnnewstring[] { "value1", "value2" };
    }publicstring Get(int id)
    {return"value "+ id;
    }
}

And it will read the “internal:origins” appSetting from the web.config.

<appSettings><addkey="webpages:Version"value="2.0.0.0"/><addkey="webpages:Enabled"value="false"/><addkey="PreserveLoginUrl"value="true"/><addkey="ClientValidationEnabled"value="true"/><addkey="UnobtrusiveJavaScriptEnabled"value="true"/><addkey="internal:origins"value="http://example.com,http://webapisample.azurewebsites.net"/></appSettings>

Implementing a custom ICorsPolicyProviderFactory

ICorsPolicyProviderFactory is an abstraction that allows you to specify how the ICorsPolicyProvider are retrieved. By default we provide the AttributeBasedPolicyProviderFactory which allows you to specify the ICorsPolicyProvider as attributes ([EnableCors], [DisableCors]). However you can extend the ICorsPolicyProviderFactory to create a centralized configuration model.

namespace System.Web.Http.Cors
{publicinterface ICorsPolicyProviderFactory
    {
        ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request);
    }
}

You can register the custom ICorsPolicyProviderFactory through SetCorsPolicyProviderFactory extension method.

publicstaticclass HttpConfigurationExtensions
{// other extensions removed for claritypublicstaticvoid SetCorsPolicyProviderFactory(this HttpConfiguration httpConfiguration, ICorsPolicyProviderFactory corsPolicyProviderFactory);
}
Sample

Here is a custom implementation of ICorsPolicyProviderFactory that allows you to configure the CORS settings through your own CorsConfiguration class instead of attributes.

publicclass ConfigBasedPolicyProviderFactory : ICorsPolicyProviderFactory
{private CorsConfiguration _configuration;public ConfigBasedPolicyProviderFactory(CorsConfiguration configuration)
    {
        _configuration = configuration;
    }public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
    {var routeData = request.GetRouteData();if (routeData == null || !routeData.Values.Keys.Contains("controller"))
        {returnnull;
        }var controller = routeData.Values["controller"] asstring;return _configuration.GetPolicyForRequest(controller);
    }
}
publicclass CorsConfiguration
{private Dictionary<string, EnableCorsAttribute> _settings = new Dictionary<string, EnableCorsAttribute>();publicvoid AddSetting(string controller, EnableCorsAttribute policyProvider)
    {
        _settings.Add(controller, policyProvider);
    }publicvirtual EnableCorsAttribute GetPolicyForRequest(string controller)
    {
        EnableCorsAttribute policyProvider;
        _settings.TryGetValue(controller, out policyProvider);return policyProvider;
    }
}

Once the ConfigBasedPolicyProviderFactory is registered, it will enable CORS on ValuesController and UsersController.

CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.AddSetting("Values", new EnableCorsAttribute());
corsConfig.AddSetting("Users", new EnableCorsAttribute { Origins = new[] { "http://localhost" } });
config.SetCorsPolicyProviderFactory(new ConfigBasedPolicyProviderFactory(corsConfig));

config.EnableCors();

Source code checked in, #601a6c18fb98

$
0
0
Rename ODataEntrySerializer and ODataEntryDeserializer 1) Renames 2) Minor change caching logic in DefaultODataDeserializerProvider and DefaultODataSerializerProvider.

New Post: OData Routing

$
0
0
Exact same issue here, right down to returning IQueryable<T> and the SelectMany LINQ expression. I can get "one to one" relationships working fine, but not "one to many".

Ever figure this out?

New Post: OData Routing

$
0
0
zlangner wrote:
Sorry for not getting back to you sooner. It would seem I've been living out of a meeting room this week. I just wanted to let you know that your solution does work, but I'm still wondering what is HasNavigationPropertiesLink for? I noticed it when I was using the ODataModelBuilder to build the model for my ODataRoute. The function exists in EntitySetConfiguration. If you or anyone has an example of it's use or can explain why someone might use it I would appreciate the knowledge. It's hard to make good use of a tool kit if you don't know what all the tools are.
HasNavigagationPropertiesLink is used to configure the navigation links for an entity set. If you are using the ODataConventionModelBuilder, the model builder already takes care of setting up the navigation links following the OData link conventions. If for some reason (like lets says containment) you want to deviate from OData URL conventions, you can use this method.

New Post: OData Routing

$
0
0
ShadowChaser wrote:
Exact same issue here, right down to returning IQueryable<T> and the SelectMany LINQ expression. I can get "one to one" relationships working fine, but not "one to many".

Ever figure this out?
@ShadowChaser: I did not understand what part is not working. Can you share more details or some code?

New Post: Status of OData support

$
0
0
Ah, right, well technically that's still correct as we don't update the core runtime bits (MVC/Web API) in the 2012.2 release. We added framework bits (ex OData) but they all build on the 4.0 runtime.

Daniel Roth

Edited Feature: Add support for x-http-method [456]

$
0
0
MVC currently supports this. We should consider adding the same to ASP.NET Web API.

Edited Issue: Remove default namespaces from XML in Web API [413]

$
0
0
The XML serialisation process injects default namespaces into the generated XML:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

These can be supressed in the XmlSerializer by explicitly passing in an XmlSerializerNamespaces object to the Serialize method.

I would be happy to develop a fix for this and submit a pull request if the team feel it is useful.

Edited Issue: HttpControllerHandler.ConvertResponse prevents manual writing of Pragma header [410]

$
0
0
This was originally a discussion here: http://aspnetwebstack.codeplex.com/discussions/389092 but I think it's better suited as an issue.

With the logic currently in this method it's impossible to write to the Pragma response header unless you also set the CacheControl header.

See http://stackoverflow.com/questions/11659525/writing-the-pragma-header-in-a-delegatinghandler-in-asp-net-web-api, which also links to a related question on Programmers (http://programmers.stackexchange.com/questions/158198/http-response-header-for-a-unique-request-id-for-rest-service) which describes why I might want to use the Pragma header.

E.g:

Response.Headers.Add("pragma", some_value);

Will not work, because of the following code in ConvertResponse:

CacheControlHeader cacheControl = response.Headers.CacheControl;
// TODO 335085: Consider this when coming up with our caching story
if (cacheControl == null)
{
// DevDiv2 #332323. ASP.NET by default always emits a cache-control: private header.
// However, we don't want requests to be cached by default.
// If nobody set an explicit CacheControl then explicitly set to no-cache to override the
// default behavior. This will cause the following response headers to be emitted:
// Cache-Control: no-cache
// Pragma: no-cache
// Expires: -1
httpContextBase.Response.Cache.SetCacheability(HttpCacheability.NoCache);
}

The comments do speak for themselves; although I think that this should not rely on Asp.Net's handling of the HttpCacheability.NoCache directive, as that writes the three headers mentioned with impunity. Thus, if a Pragma (in particular), has been added upstream it will get wiped. In a platform like the Web API, the upstream code should have full and 'natural' control of the web responses that are sent.

Currently the solution to this is to manually add a CacheControlHeader to the HttpResponseMessage:

Response.Headers.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue()
{
NoCache = true
};
toLog.Response.Headers.Add("pragma", some_value);

Which, as we see from the above code then disables the if statement. I'm not entirely sure that this on its own, however, is enough actually disable caching in all cases, I think we do need Expires also.

The Pragma header in this case isn't just intended for the no-cache value, it can also be used to carry application-specific values that, crucially, should not be stripped by downstream proxies, and which makes it a good choice for sending things like unique request IDs - which is what I intended to use it for.

Edited Issue: Validation should honor member field in ValidationResult [362]

$
0
0
Reported by a user:

The problem I am having is with models like:

// the view model
public class RegisterModel : IValidatableObject
{

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (somethingIsWrong)
yield return new ValidationResult("Something went wrong", new[] { "Field1" });

if (somethingElseIsWrong)
yield return new ValidationResult("Something went wrong", new[] { "Field2" });

}
}

// the controller action
public HttpResponseMessage Post(RegisterModel model)
{
return Request.CreateResponse(HttpStatusCode.OK);
}

In the controller I expect this error to be retrievable from ModelState["model.Field1"] but instead it is ModelState["model"]. Additionally, because the field name is dropped there can be only one error. If somethingIsWrong && somethingElseIsWrong only one of the errors is available.

Created Issue: HelpPage not showing documentation for actions which have parameters as Nested types [905]

$
0
0
From here:
[http://stackoverflow.com/questions/15410057/webapi-help-page-for-complex-type-in-uri](http://stackoverflow.com/questions/15410057/webapi-help-page-for-complex-type-in-uri)

Repro:
Copy the following class and enable Xml documentation on the project settings and also in HelPage's HelpPageConfig.cs
```
using System.Web.Http;

namespace MvcApplication31.Controllers
{
public class UsersController : ApiController
{
public class Preferences
{
public string Theme { get; set; }

public string Size { get; set; }
}

/// <summary>
/// Saves users' preferences
/// </summary>
/// <param name="pref">Preferences of the user</param>
public string SavePreferences(Preferences pref)
{
return "value";
}
}
}
```

Actual: "No Documentation Available"
Expected: comments specified for the action.

Edited Issue: HelpPage not showing documentation for actions which have parameters as Nested types [905]

$
0
0
From here:
[http://stackoverflow.com/questions/15410057/webapi-help-page-for-complex-type-in-uri](http://stackoverflow.com/questions/15410057/webapi-help-page-for-complex-type-in-uri)

Repro:
Copy the following class and enable Xml documentation on the project settings and also in HelPage's HelpPageConfig.cs
```
using System.Web.Http;

namespace MvcApplication31.Controllers
{
public class UsersController : ApiController
{
public class Preferences
{
public string Theme { get; set; }

public string Size { get; set; }
}

/// <summary>
/// Saves users' preferences
/// </summary>
/// <param name="pref">Preferences of the user</param>
public string SavePreferences(Preferences pref)
{
return "value";
}
}
}
```

Actual: "No Documentation Available"
Expected: comments specified for the action.

Edited Issue: HttpConfiguration.ShouldIncludeErrorDetail should be public [361]

$
0
0
This would allow users to easily decide in their action whether or not they should send error detail for custom HttpErrors.

Commented Issue: PushstreamContent in Win8 App is not working [324]

$
0
0
I am hitting an issue with using PushStreamContent in the Windows store app. I don’t see the same issue in the traditional console app though.

It’s a simple scenario where I am ‘POST’ing some small data to a service using PushStreamContent as below.

HttpClient client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "http://.../SimpleMvcWebAPIApplication/api/values");
request.Content = new PushStreamContent((stream, httpContent, transportContext) =>
{
using (var streamWriter = new StreamWriter(stream))
{
string data = "\"hello world\"";
streamWriter.Write(data);
streamWriter.Flush();
}
}, "application/json");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();

It fails as below.

System.ObjectDisposedException was unhandled by user code
HResult=-2146232798
Message=Cannot access a closed Stream.
Source=mscorlib
ObjectName=""
StackTrace:
at System.IO.__Error.StreamIsClosed()
at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
at System.Net.Http.HttpContent.<>c__DisplayClassf.<LoadIntoBufferAsync>b__d(Task copyTask)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at App5.App.<SimpleWebAPIService_Write_Temp1>d__f.MoveNext() in c:\personal\maying\WinRT\client\WinRTClient\App.xaml.cs:line 368
InnerException:

Comments: I am guessing in user code, it should not close the stream.

Edited Issue: PushstreamContent in Win8 App is not working [324]

$
0
0
I am hitting an issue with using PushStreamContent in the Windows store app. I don’t see the same issue in the traditional console app though.

It’s a simple scenario where I am ‘POST’ing some small data to a service using PushStreamContent as below.

HttpClient client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "http://.../SimpleMvcWebAPIApplication/api/values");
request.Content = new PushStreamContent((stream, httpContent, transportContext) =>
{
using (var streamWriter = new StreamWriter(stream))
{
string data = "\"hello world\"";
streamWriter.Write(data);
streamWriter.Flush();
}
}, "application/json");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();

It fails as below.

System.ObjectDisposedException was unhandled by user code
HResult=-2146232798
Message=Cannot access a closed Stream.
Source=mscorlib
ObjectName=""
StackTrace:
at System.IO.__Error.StreamIsClosed()
at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
at System.Net.Http.HttpContent.<>c__DisplayClassf.<LoadIntoBufferAsync>b__d(Task copyTask)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at App5.App.<SimpleWebAPIService_Write_Temp1>d__f.MoveNext() in c:\personal\maying\WinRT\client\WinRTClient\App.xaml.cs:line 368
InnerException:

Commented Issue: PushstreamContent in Win8 App is not working [324]

$
0
0
I am hitting an issue with using PushStreamContent in the Windows store app. I don’t see the same issue in the traditional console app though.

It’s a simple scenario where I am ‘POST’ing some small data to a service using PushStreamContent as below.

HttpClient client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "http://.../SimpleMvcWebAPIApplication/api/values");
request.Content = new PushStreamContent((stream, httpContent, transportContext) =>
{
using (var streamWriter = new StreamWriter(stream))
{
string data = "\"hello world\"";
streamWriter.Write(data);
streamWriter.Flush();
}
}, "application/json");

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();

It fails as below.

System.ObjectDisposedException was unhandled by user code
HResult=-2146232798
Message=Cannot access a closed Stream.
Source=mscorlib
ObjectName=""
StackTrace:
at System.IO.__Error.StreamIsClosed()
at System.IO.MemoryStream.Seek(Int64 offset, SeekOrigin loc)
at System.Net.Http.HttpContent.<>c__DisplayClassf.<LoadIntoBufferAsync>b__d(Task copyTask)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at App5.App.<SimpleWebAPIService_Write_Temp1>d__f.MoveNext() in c:\personal\maying\WinRT\client\WinRTClient\App.xaml.cs:line 368
InnerException:

Comments: See pushstreamcontent sample in http://aspnet.codeplex.com/SourceControl/changeset/view/75a56ec99968#Samples/WebApi/PushContentControllerSample/PushContentController/Controllers/PushContentController.cs We should not put using around streamwriter, which will dispose the underlying stream

Reviewed: v4.0 RTM (三月 14, 2013)

$
0
0
Rated 5 Stars (out of 5) - thanks....

Edited Issue: Throw exception from ITraceWriter.Trace cause self-host down. [319]

$
0
0
It can be solved by wrapping try/catch structure around all logics in TraceWriter. However it would be nice to provide a inner established mechanism just in cause user provide a bad implementation.
Viewing all 7925 articles
Browse latest View live