Quantcast
Channel: ASPNETWebStack Issue Tracker Rss Feed
Viewing all 7215 articles
Browse latest View live

Commented Unassigned: Add overloads taking a CancellationToken parameter [983]

$
0
0
Currently some of TAP-based methods in the aspnetwebstack libraries does not have overloads with _CancellationToken_ parameter. For instance following classes:

_System.Net.Http_: HttpContent and successors.
```
HttpContent: ReadAsStringAsync, ReadAsByteArrayAsync, ReadAsStreamAsync, etc.
```
_System.Net.Http.Formatting_: HttpContent extensions.
```
HttpContentMessageExtensions: ReadAsHttpRequestMessageAsync
HttpContentMultipartExtensions: ReadAsMultipartAsync
HttpContentFormDataExtensions: ReadAsFormDataAsync
HttpContentMessageExtensions: ReadAsHttpRequestMessageAsync
MultipartStreamProvider: ExecutePostProcessingAsync
```
_System.Net.Http.Formatting_: MediaTypeFormatter and successors.
```
MediaTypeFormatter: ReadFromStreamAsync, WriteToStreamAsync
BufferedMediaTypeFormatter
FormUrlEncodedMediaTypeFormatter
JsonMediaTypeFormatter
XmlMediaTypeFormatter
```
_System.Web.Http_: Model binder which breaks cancellable pipeline.
```
FormatterParameterBinding: ReadContentAsync
```
Methods of above classes potentially may be executed for a long time period. In addition if we're trying to create custom _MediaTypeFormatter_ we unable to cancel _ReadFromStreamAsync_ and _WriteToStreamAsync_ methods.

I suppose that it will be great if such methods will contain an overloads with a _CancellationToken_ parameter, which should be properly integrated into Web API message processing pipeline.

Code sample how it can be refactored: https://aspnetwebstack.codeplex.com/SourceControl/network/forks/dtretyakov/CancellationToken/contribution/4472

P.S. Discussions looks dead - no answers for over 2 weeks: http://aspnetwebstack.codeplex.com/discussions/438601
Comments: I agree, it is needed to add such feature. In our case, we're using ReadAsMultipartAsync() for stream-based upload of large files and had to throw OperationCancelledException() in our Stream wrapper, that contains cancellation checking logic and checks property called CancelPending of the associated I/O descriptor class in overridden Read/Write methods. if a client wants to cancel upload request (via AJAX), then I/O descriptor's property CancelPending is set to true and whenever parser's Task calls Read/Write method on the Stream, this property is being checked before calling underlying stream's methods. The exception, that is thrown in Read/Write methods causes Task returned by ReadAsMultipartAsync() to stop further processing that is being indicated by Task.IsFaulted in the MVC controller and check Task's Error property. Nevertheless, this is not so clean, but the only way for us how to indirectly stop the upload processing task whose "Cancel" is initiated from the server's side upon receiving client's cancel request. The advantage in our case is, that we can insert our cancellation logic layer via Stream wrapper class into the MIME multipart upload parser, which gets stream by calling GetStream() method from the passed MultipartStreamProvider. However, in other cases where injecting own cancellation logic is impossible, the cancellation token support in the cases you mentioned is really welcome.

Edited Unassigned: MVC: Make non-generic TryUpdateModel methods [1071]

$
0
0
Sometimes it is necessary to make a polymorphic binding of model on the basis of the interface. But if one pass the model of a particular type, wich implements the necessary interface, the binding doesn't occur because the TryUpdateMethod method is generic. Make overloads, where only the object model would be transfered to the entrance of the method:

bool TryUpdateModel(object model)
bool TryUpdateModel(object model, string prefix)

etc.

Example of usage:

```
public ActionResult Process(SomeDescriminatorEnum someDescriminator)
{
IMyModel model = GetConcreteForm(someDescriminator);
if (TryUpdateModel(model))
{
// ...
}
// ...
}
```

Edited Unassigned: Add Feature to WebGrid [1069]

$
0
0
Add opportunity to customize header output. Like it made with "Format" property. Or just change Header type to object. To have a way for manage output.

```
namespace System.Web.Helpers {
public class WebGridColumn {

public bool CanSort { get; set; }

public string ColumnName { get; set; }

public Func<dynamic, object> Format { get; set; }

public __object__ Header { get; set; }

public string Style { get; set; }

}

}
```

Closed Issue: Add AuthenticationFilterAttributeTracer wrapper for AuthenticationFilter [946]

$
0
0
The authentication filter won’t work under tracing mode as tracer will wrap the auth filter as a FilterTracer which is just an IFilter. FilterGrouping.SelectAvailable can't select correct authentication filter with the wrapper.

In order to fix it, a strong typed tracer AuthenticationFilterAttributeTracer should be added and inherits from AuthenticationFilterAttribute.
Comments: Verified in latest bits

Closed Issue: Null Ref Exception from ODataEntityDeserializer.ReadEntryOrFeed [1026]

$
0
0
To repro the issue, define entity model as:

[EntitySet("Security_ArrayModel")]
[DataServiceKey("ID")]
public class Security_ArrayModel
{
public int ID { get; set; }
public List<string> StringArray { get; set; }
public List<Security_ComplexModel> ComplexArray { get; set; }
public List<Security_NestedModel> NavigationCollection { get; set; }
}

[EntitySet("Security_NestedModel")]
[DataServiceKey("ID")]
public class Security_NestedModel
{
public int ID { get; set; }
public Security_NestedModel Nest { get; set; }
}

public class Security_ComplexModel
{
public string Name { get; set; }
}

Use Security_ArrayModel as EntitySet and Post following payload to it:

POST http://hongye2:9001/Security_ArrayModel HTTP/1.1
Content-Type: application/json; odata=fullmetadata; charset=utf-8
Host: hongye2:9001
Content-Length: 104
Expect: 100-continue
Connection: Keep-Alive

{"ID":0,"StringArray":[""],"ComplexArray":[{"Name":null}],"NavigationCollection":[{"ID":0,"Nest":null}]}

It throws null ref exception with call stack:
The call stack is:

> System.Web.Http.OData.dll!System.Web.Http.OData.Formatter.Deserialization.ODataEntityDeserializer.ReadEntryOrFeed(Microsoft.Data.OData.ODataReader reader) Line 345 + 0x2f bytes C#
System.Web.Http.OData.dll!System.Web.Http.OData.Formatter.Deserialization.ODataEntityDeserializer.Read(Microsoft.Data.OData.ODataMessageReader messageReader, System.Web.Http.OData.Formatter.Deserialization.ODataDeserializerContext readContext) Line 62 + 0x8 bytes C#
System.Web.Http.OData.dll!System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.ReadFromStreamAsync.AnonymousMethod__4() Line 325 + 0x11 bytes C#
System.Web.Http.OData.dll!System.Threading.Tasks.TaskHelpers.RunSynchronously<object>(System.Func<object> func, System.Threading.CancellationToken cancellationToken) Line 243 + 0xb bytes C#
System.Web.Http.OData.dll!System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.ReadFromStreamAsync(System.Type type, System.IO.Stream readStream, System.Net.Http.HttpContent content, System.Net.Http.Formatting.IFormatterLogger formatterLogger) Line 270 + 0x37 bytes C#
System.Web.Http.dll!System.Web.Http.Tracing.Tracers.MediaTypeFormatterTracer.ReadFromStreamAsync.AnonymousMethod__6() Line 204 + 0x37 bytes C#
System.Web.Http.dll!System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEndAsync<object>(System.Web.Http.Tracing.ITraceWriter traceWriter, System.Net.Http.HttpRequestMessage request, string category, System.Web.Http.Tracing.TraceLevel level, string operatorName, string operationName, System.Action<System.Web.Http.Tracing.TraceRecord> beginTrace, System.Func<System.Threading.Tasks.Task<object>> execute, System.Action<System.Web.Http.Tracing.TraceRecord,object> endTrace, System.Action<System.Web.Http.Tracing.TraceRecord> errorTrace) Line 437 + 0xb bytes C#
System.Web.Http.dll!System.Web.Http.Tracing.Tracers.MediaTypeFormatterTracer.ReadFromStreamAsync(System.Type type, System.IO.Stream readStream, System.Net.Http.HttpContent content, System.Net.Http.Formatting.IFormatterLogger formatterLogger) Line 190 + 0x1a0 bytes C#
System.Net.Http.Formatting.dll!System.Net.Http.HttpContentExtensions.ReadAsAsyncCore<object>(System.Net.Http.HttpContent content, System.Type type, System.Net.Http.Formatting.IFormatterLogger formatterLogger, System.Net.Http.Formatting.MediaTypeFormatter formatter) Line 151 + 0x3d bytes C#
System.Net.Http.Formatting.dll!System.Net.Http.HttpContentExtensions.ReadAsAsync<object>(System.Net.Http.HttpContent content, System.Type type, System.Collections.Generic.IEnumerable<System.Net.Http.Formatting.MediaTypeFormatter> formatters, System.Net.Http.Formatting.IFormatterLogger formatterLogger) Line 145 + 0x3f bytes C#
System.Net.Http.Formatting.dll!System.Net.Http.HttpContentExtensions.ReadAsAsync(System.Net.Http.HttpContent content, System.Type type, System.Collections.Generic.IEnumerable<System.Net.Http.Formatting.MediaTypeFormatter> formatters, System.Net.Http.Formatting.IFormatterLogger formatterLogger) Line 58 + 0x16 bytes C#
System.Web.Http.dll!System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(System.Net.Http.HttpRequestMessage request, System.Type type, System.Collections.Generic.IEnumerable<System.Net.Http.Formatting.MediaTypeFormatter> formatters, System.Net.Http.Formatting.IFormatterLogger formatterLogger) Line 88 + 0x11 bytes C#
System.Web.Http.dll!System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsyncCore(System.Web.Http.Metadata.ModelMetadataProvider metadataProvider, System.Web.Http.Controllers.HttpActionContext actionContext, System.Web.Http.Controllers.HttpParameterDescriptor paramFromBody, System.Type type, System.Net.Http.HttpRequestMessage request, System.Net.Http.Formatting.IFormatterLogger formatterLogger, System.Threading.CancellationToken cancellationToken) Line 120 + 0x3f bytes C#
System.Web.Http.dll!System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(System.Web.Http.Metadata.ModelMetadataProvider metadataProvider, System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) Line 112 + 0x1f bytes C#
System.Web.Http.OData.dll!System.Web.Http.OData.PerRequestParameterBinding.ExecuteBindingAsync(System.Web.Http.Metadata.ModelMetadataProvider metadataProvider, System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) Line 57 + 0x16 bytes C#

Comments: Verified in latest bits

Commented Unassigned: [WebApiOnOwin] Response sent in chunked encoding when it does not have any content [993]

$
0
0
When there is no content assigned to a HttpResponseMessage, the response is being sent in a chunked encoding format.

Example:
```
public HttpResponseMessage ReturnNoContent()
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
```

__Attached__ a standalone repro.

Expected:
Has chunked encoding header?: __False__
Has chunked encoding header?: False
Has chunked encoding header?: False

Actual:
Has chunked encoding header?: __True__
Has chunked encoding header?: False
Has chunked encoding header?: False
Comments: We should fix this. It should be trivial to address.

Commented Issue: Broken Image link in Bing SearchBox helper [624]

$
0
0
To reproduce this, follow these steps:

1. Create a new site that references Microsoft.Web.Helpers.
2. Add @Bing.SearchBox to one of the pages.
3. Navigate to the page in the browser of your choice.

Result: The search button image will be broken. This appears to be a recent development.
Expected: We should be using a current, valid image for the search button. It looks like Bing is currently using a sprite from the image file http://www.bing.com/fd/s/a/sw17.png


Comments: I was not aware of this issue and completed the whole site using this. The site is ready except the Bing Image. Is it possible to get quick fix sooner?

Created Unassigned: [WebPages]: Update MimeMapping.cs to be match IIS8 applicationHost.config [1072]

$
0
0
The file was generated from the mimeMap in %System32%\inetsrv\config\applicationHost.config and it looks like IIS 8 has some slightly different mime mappings. It should probably be updated to match this file although the utility of it is highly questionable.

Commented Issue: application/json should return json verbose when MaxDataServiceVersion is 2.0 [830]

$
0
0
We should return json verbose payload when old client requests for json. This is the same behavior as WCF DS.

Currently, we always returns json light payload and fails when MaxODataServiceVersion is lower than 3.0.

The fix is to make CanWriteType smarter about DataServiceVersion, or won't fix it as we are only V3.0 service.
Comments: We are seeing a similar issue, except that we just get a generic error message. This request was issued by Pebble Reports. The problem goes away if I issue the same request from Fiddler, without the MaxDataServiceVersion header. Request: GET https://odata.mysite.com/odata/resource HTTP/1.1 User-Agent: Microsoft ADO.NET Data Services MaxDataServiceVersion: 2.0;NetFx SL-User-Agent: OData Reporting Accept: application/atom+xml,application/xml Accept-Charset: UTF-8 Response: <?xml version="1.0" encoding="utf-8"?> <m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"> <m:code /> <m:message xml:lang="en-US">An error has occurred.</m:message> </m:error>

Edited Issue: [WebApiOnOwin] Response sent in chunked encoding when it does not have any content [993]

$
0
0
When there is no content assigned to a HttpResponseMessage, the response is being sent in a chunked encoding format.

Example:
```
public HttpResponseMessage ReturnNoContent()
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
```

__Attached__ a standalone repro.

Expected:
Has chunked encoding header?: __False__
Has chunked encoding header?: False
Has chunked encoding header?: False

Actual:
Has chunked encoding header?: __True__
Has chunked encoding header?: False
Has chunked encoding header?: False

Commented Issue: [WebApiOnOwin] Response sent in chunked encoding when it does not have any content [993]

$
0
0
When there is no content assigned to a HttpResponseMessage, the response is being sent in a chunked encoding format.

Example:
```
public HttpResponseMessage ReturnNoContent()
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
```

__Attached__ a standalone repro.

Expected:
Has chunked encoding header?: __False__
Has chunked encoding header?: False
Has chunked encoding header?: False

Actual:
Has chunked encoding header?: __True__
Has chunked encoding header?: False
Has chunked encoding header?: False
Comments: Fixed: https://aspnetwebstack.codeplex.com/SourceControl/changeset/ef58399a5e0ee7a850f3ba1136ebf10dd6887649

Edited Feature: More virtual extensibility to XmlMediaTypeFormatter and make it instance-type-aware [189]

$
0
0
I'm going to try and keep this brief - but it might be difficult.

In the project I'm writing at the moment, I've customised the XML formatter to correctly serialize an instance based on it's actual type rather than the method's return type - paralleling what the JSON.Net serialiser does; which fixes a bug with XML content for the following service:

interface IFoo{
string Bar { get; set; }
}

class Foo : IFoo {
public string Bar { get; set; }
}

public class ExampleController : ApiController
{
public IFoo GetExample(){
return new Foo() { Bar = "Hello World!" };
}
}

When executed as JSON content, you get a JSON representation of the Foo.

When executed as XML content, the operation fails because the DataContractSerializer expects Foo to be added as a known type.

This can be fixed by changing the return type of the method - however, in my current project this just isn't desirable; as it's a multi-tenant application where controllers can be overriden based on request hostname; and the actual return types of the underlying service operations only have to implement the interface - but could have many more members specific to their remote operation.

To fix this - I created an 'Ex' version of the formatter - that picks up some data added by an ActionFilter which is used by the programmer to state declaratively that XML serialization should consider the whole-object, not just the static return type. I attach that code.

You'll notice that I've had to use the GetPerRequestFormatterInstance for this purpose - which is not ideal. More on that in a moment.

This solution does not, nor can it, solve cases where an IEnumerable<IFoo> or IDictionary<string, IFoo> will be returned. Again, the JSON.Net serializer is quite happy with this scenario, whereas the XML one is not.

In this case, it would be necessary to customise the actual serializer instance that is constructed based on the instance of the enumerable being serialized - a simple dynamic implementation being to forward-scan an IEnumerable or IDictionary (although IDictionary can be treated as IEnumerable<KeyValuePair<TKey, TValue>>) looking for all instances whose actual types are different to the static type of the generic, and then adding those to a dynamic list of known types.

This cannot be done in the current codebase - the creation of the serializer is private. However, making it virtual won't help on it's own either, because the value to be serialized must also be passed.

Ideally we need to be able to override the serializer creation code - and have that receive not only the type to be constructed, but also the value AND a state value that can be built from the request's properties (perhaps the properties themselves, or even the request).

I know that the GetPerRequestFormatterInstance method goes some way to solving this - and that it is possible to override serializers through the SetSerializer method - but the former is a very inefficient solution where lots of types are involved - and the second is clumsy. They also do not allow us to handle the case of the enumerables, as I say.

I will look forward to any furhter thoughts on this. If I've missed something blindingly obvious, then do let me know!

Commented Feature: More virtual extensibility to XmlMediaTypeFormatter and make it instance-type-aware [189]

$
0
0
I'm going to try and keep this brief - but it might be difficult.

In the project I'm writing at the moment, I've customised the XML formatter to correctly serialize an instance based on it's actual type rather than the method's return type - paralleling what the JSON.Net serialiser does; which fixes a bug with XML content for the following service:

interface IFoo{
string Bar { get; set; }
}

class Foo : IFoo {
public string Bar { get; set; }
}

public class ExampleController : ApiController
{
public IFoo GetExample(){
return new Foo() { Bar = "Hello World!" };
}
}

When executed as JSON content, you get a JSON representation of the Foo.

When executed as XML content, the operation fails because the DataContractSerializer expects Foo to be added as a known type.

This can be fixed by changing the return type of the method - however, in my current project this just isn't desirable; as it's a multi-tenant application where controllers can be overriden based on request hostname; and the actual return types of the underlying service operations only have to implement the interface - but could have many more members specific to their remote operation.

To fix this - I created an 'Ex' version of the formatter - that picks up some data added by an ActionFilter which is used by the programmer to state declaratively that XML serialization should consider the whole-object, not just the static return type. I attach that code.

You'll notice that I've had to use the GetPerRequestFormatterInstance for this purpose - which is not ideal. More on that in a moment.

This solution does not, nor can it, solve cases where an IEnumerable<IFoo> or IDictionary<string, IFoo> will be returned. Again, the JSON.Net serializer is quite happy with this scenario, whereas the XML one is not.

In this case, it would be necessary to customise the actual serializer instance that is constructed based on the instance of the enumerable being serialized - a simple dynamic implementation being to forward-scan an IEnumerable or IDictionary (although IDictionary can be treated as IEnumerable<KeyValuePair<TKey, TValue>>) looking for all instances whose actual types are different to the static type of the generic, and then adding those to a dynamic list of known types.

This cannot be done in the current codebase - the creation of the serializer is private. However, making it virtual won't help on it's own either, because the value to be serialized must also be passed.

Ideally we need to be able to override the serializer creation code - and have that receive not only the type to be constructed, but also the value AND a state value that can be built from the request's properties (perhaps the properties themselves, or even the request).

I know that the GetPerRequestFormatterInstance method goes some way to solving this - and that it is possible to override serializers through the SetSerializer method - but the former is a very inefficient solution where lots of types are involved - and the second is clumsy. They also do not allow us to handle the case of the enumerables, as I say.

I will look forward to any furhter thoughts on this. If I've missed something blindingly obvious, then do let me know!
Comments: Fixed: https://aspnetwebstack.codeplex.com/SourceControl/changeset/8305478a7e9813c8185fb9cdb14b794b348ba5c6

Commented Unassigned: EntitySetController.Get(TKey) breaks when $expand query options are added [1074]

$
0
0
This is a bug in Web API OData, nightly build. I believe this is a bug in `ODataEntityTypeSerializer`, but it is also likely a design flaw in EntitySetController.

In OData, it's valid to have a url like http://localhost/EntitySet(10)?$expand=Property1/SubProperty,Property2 , where 10 is an ID in EntitySet. I haven't verified that this is valid in the odata spec, but it's supported by WCF Data Services server and client. More importantly, such URLs are built by the WCF data services client if you create a query with `Expand` and with `where ID == 10`.

In `EntitySetController`, the default implementation of the Get(TKey) action calls `GetEntityByKey(key)`, then returns the entity or `null` if not found - so there's clearly no query support for executing the expand.

If I add the [Queryable] attribute:
``` C#

[Queryable(AllowedQueryOptions = AllowedQueryOptions.All, MaxExpansionDepth = 15)]
public virtual HttpResponseMessage Get([FromODataUri] TKey key)
{
TEntity entity = GetEntityByKey(key);
return EntitySetControllerHelpers.GetByKeyResponse(Request, entity);
}
```

and invoke such a query, all the link collections are empty (not surprising), and all the navigation properties/links throw an exception during serialization, like:

``` xml
<m:type>System.InvalidOperationException</m:type>
<m:stacktrace></m:stacktrace>
<m:internalexception>
<m:message>The EDM instance of type '[Property1Type Nullable=True]' is missing the property 'Title'.</m:message>
<m:type>System.InvalidOperationException</m:type>
<m:stacktrace> at System.Web.Http.OData.EntityInstanceContext.GetPropertyValue(String propertyName)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateStructuralProperty(IEdmStructuralProperty structuralProperty, EntityInstanceContext entityInstanceContext)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateStructuralPropertyBag(IEnumerable`1 structuralProperties, EntityInstanceContext entityInstanceContext)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.CreateEntry(SelectExpandNode selectExpandNode, EntityInstanceContext entityInstanceContext)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteObjectInline(Object graph, ODataWriter writer, ODataSerializerContext writeContext)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteExpandedNavigationProperty(KeyValuePair`2 navigationPropertyToExpand, EntityInstanceContext entityInstanceContext, ODataWriter writer)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteExpandedNavigationProperties(IDictionary`2 navigationPropertiesToExpand, EntityInstanceContext entityInstanceContext, ODataWriter writer)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteObjectInline(Object graph, ODataWriter writer, ODataSerializerContext writeContext)

at System.Web.Http.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteObject(Object graph, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)

at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)

at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext)

--- 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.GetResult()

at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__10.MoveNext()</m:stacktrace>
</m:internalexception>
```

Note that this exception occurs from serializing a null relationship object, and even though the object is null, the error message says the null object's property is missing. So the error is misleading, and it shouldn't happen.

Further, I can't add support for such queries in `Get(TKey)`, because I can't process `ODataQueryOptions` in the normal way. For more info on that, see https://aspnetwebstack.codeplex.com/workitem/1073
.

To be clear, I'd like to implement something like:

``` C#
public virtual HttpResponseMessage Get([FromODataUri] TKey key, ODataQueryOptions<TEntity> queryOptions)
{
queryOptions.Validate(QueryValidationSettings);

IQueryable<TEntity> query = GetBaseQueryable().Where(e => e.ID == key);
IQueryable queryOptionsApplied = queryOptions.ApplyTo(query);
TEntity entity = queryOptionsApplied.Cast<TEntity>().FirstOrDefault();
return EntitySetControllerHelpers.GetByKeyResponse(Request, entity);
}
```
- but I can't due to the bug in 1073.
Comments: Personally I think the design needs review, the odata implementation and EntitySetController/ AsyncEntitySetController needs to support composite key entities out of the box. Just my two pennies worth.

Commented Unassigned: $expand breaks use of Get(ODataQueryOptions) [1073]

$
0
0
Bug, or "how do I do this", in Web API OData:

Using the nightly builds to test out $expand support - note that I really really want to switch to Web API OData over WCF Data Services, because the extension points are soo much better, but I can't justify doing so until I can provide equivalent functionality.

I want to inject `ODataValidationSettings` (so I can manage them centrally instead of in per-controller attributes). I can't do that using EntitySetController, so I had to create my own base class. Here's one implementation:

``` C#

public abstract class DbSetController<TEntity, TKey, TDbContext> : ODataController
where TEntity : class
where TDbContext : DbContext
{
private readonly ODataValidationSettings _queryValidationSettings;
private readonly TDbContext _dbContext;

protected DbSetController(ODataValidationSettings queryValidationSettings, TDbContext dbContext)
{
_queryValidationSettings = queryValidationSettings;
_dbContext = dbContext;
}

protected virtual ODataValidationSettings QueryValidationSettings
{
get { return _queryValidationSettings; }
}

public virtual IQueryable<TEntity> Get(ODataQueryOptions<TEntity> queryOptions)
{
queryOptions.Validate(QueryValidationSettings);

IQueryable queryApplied = queryOptions.ApplyTo(_dbContext.Set<TEntity>());
return queryApplied.Cast<TEntity>();
}


```

This works fine for simple queries, like http://localhost/odata/Status?$top=2 .

However, it breaks as soon as I add an $expand or $select clause - I get:
``` xml
<m:internalexception>
<m:message>Unable to cast the type 'System.Web.Http.OData.Query.Expressions.SelectExpandWrapper`1' to type 'Scrum.Model.WorkItem'. LINQ to Entities only supports casting EDM primitive or enumeration types.</m:message>
<m:type>System.NotSupportedException</m:type>
<m:stacktrace> at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.ValidateAndAdjustCastTypes(TypeUsage toType, TypeUsage fromType, Type toClrType, Type fromClrType)&#xD;
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.GetCastTargetType(TypeUsage fromType, Type toClrType, Type fromClrType, Boolean preserveCastForDateTime)&#xD;
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.CreateCastExpression(DbExpression source, Type toClrType, Type fromClrType)&#xD;
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.CastMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)&#xD;
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)&#xD;
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)&#xD;
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)&#xD;
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)&#xD;
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert()&#xD;
at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)&#xD;
at System.Data.Entity.Core.Objects.ObjectQuery`1.&lt;&gt;c__DisplayClassb.&lt;GetResults&gt;b__a()&#xD;
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, Boolean throwOnExistingTransaction, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)&#xD;
at System.Data.Entity.Core.Objects.ObjectQuery`1.&lt;&gt;c__DisplayClassb.&lt;GetResults&gt;b__9()&#xD;
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.ProtectedExecute[TResult](Func`1 func)&#xD;
at System.Data.Entity.Infrastructure.ExecutionStrategy.Execute[TResult](Func`1 func)&#xD;
at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)&#xD;
at System.Data.Entity.Core.Objects.ObjectQuery`1.&lt;System.Collections.Generic.IEnumerable&lt;T&gt;.GetEnumerator&gt;b__0()&#xD;
at System.Lazy`1.CreateValue()&#xD;
at System.Lazy`1.LazyInitValue()&#xD;
at System.Lazy`1.get_Value()&#xD;
at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()&#xD;
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteFeed(IEnumerable enumerable, ODataWriter writer, ODataSerializerContext writeContext)&#xD;
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteObjectInline(Object graph, ODataWriter writer, ODataSerializerContext writeContext)&#xD;
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteObject(Object graph, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)&#xD;
at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)&#xD;
at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext)&#xD;
--- End of stack trace from previous location where exception was thrown ---&#xD;
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)&#xD;
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)&#xD;
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()&#xD;
at System.Web.Http.WebHost.HttpControllerHandler.&lt;WriteBufferedResponseContentAsync&gt;d__10.MoveNext()</m:stacktrace>
</m:internalexception>
```

Figuring that it may be an issue with entity framework not liking the other types in its expression tree, I tried this implementation:

``` C#
public virtual HttpResponseMessage Get(ODataQueryOptions<TEntity> queryOptions)
{
queryOptions.Validate(QueryValidationSettings);

IQueryable queryApplied = queryOptions.ApplyTo(_dbContext.Set<TEntity>());
var list = new List<object>(100);
foreach (var o in queryApplied)
{
list.Add(o);
}
return Request.CreateResponse(list.Cast<TEntity>());
}
```

This breaks as follows:
``` xml

<?xml version="1.0" encoding="utf-8"?>
<m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<m:code />
<m:message xml:lang="en-US">An error has occurred.</m:message>
<m:innererror>
<m:message>The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.</m:message>
<m:type>System.InvalidOperationException</m:type>
<m:stacktrace></m:stacktrace>
<m:internalexception>
<m:message>Unable to cast object of type 'System.Web.Http.OData.Query.Expressions.SelectExpandWrapper`1[Scrum.Model.WorkItem]' to type 'Scrum.Model.WorkItem'.</m:message>
<m:type>System.InvalidCastException</m:type>
<m:stacktrace> at System.Linq.Enumerable.&lt;CastIterator&gt;d__b1`1.MoveNext()&#xD;
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteFeed(IEnumerable enumerable, ODataWriter writer, ODataSerializerContext writeContext)&#xD;
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteObjectInline(Object graph, ODataWriter writer, ODataSerializerContext writeContext)&#xD;
at System.Web.Http.OData.Formatter.Serialization.ODataFeedSerializer.WriteObject(Object graph, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)&#xD;
at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)&#xD;
at System.Web.Http.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext)&#xD;
--- End of stack trace from previous location where exception was thrown ---&#xD;
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)&#xD;
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)&#xD;
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()&#xD;
at System.Web.Http.WebHost.HttpControllerHandler.&lt;WriteBufferedResponseContentAsync&gt;d__10.MoveNext()</m:stacktrace>
</m:internalexception>
</m:innererror>
</m:error>
```

It looks like I can extract the element values from `SelectExpandWrapper`, but it's not clear that's the right way to go - please point me at a better example if there's a better approach.

Comments: That is the expected behavior. Once $select or $expand is applied to IQueryable<TEntity>, the result is no longer IQueryable<TEntity>. It becomes IQueryable<SelectExpandWrapper<TEntity>> as $select and $expand are shape changing queries. I have some sample code for supporting $select and $expand using ODataQueryOptions<T> [here](https://aspnetwebstack.codeplex.com/wikipage?title=%24select%20and%20%24expand%20support&referringTitle=Specs). Please refer to sample number 4. It is slightly more complicated than usual due to the missing Request.CreateResponse that takes runtime type.

Closed Issue: [WebApiOnOwin] Response sent in chunked encoding when it does not have any content [993]

$
0
0
When there is no content assigned to a HttpResponseMessage, the response is being sent in a chunked encoding format.

Example:
```
public HttpResponseMessage ReturnNoContent()
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
```

__Attached__ a standalone repro.

Expected:
Has chunked encoding header?: __False__
Has chunked encoding header?: False
Has chunked encoding header?: False

Actual:
Has chunked encoding header?: __True__
Has chunked encoding header?: False
Has chunked encoding header?: False
Comments: Verified.

Edited Issue: Expose the default logic of link generation to enable re-using logic. [536]

$
0
0
I agree that its easy to create links ourselves, but its natural and easier to just fallback to the default logic too.

Scenarios:
a. I would like to build a 'Transient' action on Product called "ExtendSupportDate". In my HasActionLink logic, I check to see if the given entity instance context(Product) is discontinued or not. if discontinued, i do not want to 'advertise' the action "ExtendSupportDate" otherwise I would like to re-use whatever logic the default Action link convention generates.
b. Similar as above, a scenario where you don't want to show Edit link for some entity instances and for the rest of them would want to use the default Edit link convention that we have.

Currently for scenario 'a', i am doing the following:
----------------------------------------------------------
static IEdmModel GetImplicitEdmModel()
{
ODataConventionModelBuilder modelBuilder = new ODataConventionModelBuilder();
var products = modelBuilder.EntitySet<Product>("Products");
var productFamilies = modelBuilder.EntitySet<ProductFamily>("ProductFamilies");
var suppliers = modelBuilder.EntitySet<Supplier>("Suppliers");

var config = products.EntityType.TransientAction("ExtendSupportDate");
config.Parameter<DateTime>("newDate");
config.ReturnsFromEntitySet<Product>("Products");
config.HasActionLink(eic =>
{
//Do not advertise 'ExtendSupportDate' for discontinued products
if(eic.EntityType.Name == "DiscontinuedProduct")
return null;

//Advertise for the rest of them
Product pd = (Product)eic.EntityInstance;

return new Uri(eic.UrlHelper.Link(ODataRouteNames.InvokeBoundAction, new {
controller = eic.EntitySet.Name,
boundId = pd.ID,
odataAction = "ExtendSupportDate" }));
});

return modelBuilder.GetEdmModel();
}

Closed Issue: [WebApiOnOwin]Provide virtual methods on OwinBufferPolicySelector [994]

$
0
0
The current signature of OwinBufferPolicySelector is the following:

We should make the UseBufferedInputStream & UseBufferedOutputStream methods overridable.

```
public class OwinBufferPolicySelector : IHostBufferPolicySelector
{
public OwinBufferPolicySelector();

public bool UseBufferedInputStream(object hostContext);
public bool UseBufferedOutputStream(HttpResponseMessage response);
}
```
Comments: no important scenarios are identified for this bug.

Closed Issue: [AttributeRouting]Generated route name suffixes should be in the same order as the order of routes. [961]

$
0
0
In the case where action names are the same for multiple actions, to keep route names unique in the route collection, we dynamically generate the names with suffixes like Products.Get1, Products.Get2 etc.

These route suffixes should honor the order of the routes in the route collection and generate the appropriate suffixes:

Example:
```
[RoutePrefix("api/values")]
public class ValuesController : ApiController
{
// GET api/values
[HttpGet(RouteOrder = 2)]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}

// GET api/values/5
[HttpGet("{id}", RouteOrder = 1)]
public string Get(int id)
{
return "value";
}
}
```
__Actual__:
Following are the routes in the route collection __in order__:
1.
routeName: Values.Get2
routeTemplate: api/values/{id}
controller: Values
action: Get

2.
routeName: Values.Get1
routeTemplate: api/values
controller: Values
action: Get

__Expected__:
1.
routeName: Values.Get1
routeTemplate: api/values/{id}
controller: Values
action: Get

2.
routeName: Values.Get2
routeTemplate: api/values
controller: Values
action: Get
Comments: As the comment from HongMei says, if the user cares he can do that already.

Edited Issue: [AttributeRouting]Handle scenario when multiple route prefixes are used and there are explicit RouteNames on actions [959]

$
0
0
Currently the following would cause a problem, as we try to create 2 routes(one for each route prefix) with the same route name calle "GetSingleSample".

```
[RoutePrefix("api/test")]
[RoutePrefix("api/samples/test")]
public class SampleController : ApiController
{
[HttpGet("{id}", RouteName="GetSingleSample")]
public string Get(int id)
{
return "Get" + id;
}
}
```

Error:
A route named 'GetAllSamples' is already in the route collection. Route names must be unique.
Parameter name: name

Also while fixing this bug, we need to think of how can one generate Uri links based on particular route-prefixes too.
Viewing all 7215 articles
Browse latest View live