Skip to content

Commit

Permalink
Fix #93: The Request property of ODataMediaTypeFormatter get modified.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kai Yang committed Jun 8, 2016
1 parent 7df0890 commit 50605f5
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using System.Web.OData;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using System.Web.OData.Formatter;
using System.Web.OData.Formatter.Deserialization;
using System.Web.OData.Formatter.Serialization;
using FluentAssertions;
using Microsoft.OData.Core;
using Microsoft.OData.Edm;
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using NUnit.Framework;
using Owin;
Expand Down Expand Up @@ -43,6 +50,24 @@ public async Task It_consolidates_tags_in_final_swagger_model()
await ValidationUtils.ValidateSwaggerJson();
}
}

[Test]
public async Task It_serializes_web_api_model()
{
Action<SwaggerDocsConfig> config = c => c.DocumentFilter<ApplySharedModelsDocumentation>();
using (WebApp.Start(HttpClientUtils.BaseAddress, appBuilder => SharedModelsSetup.ConfigurationWithFormatters(appBuilder, config, typeof(SharedModelsSetup.SharedModelsController), typeof(SharedModelsSetup.SharedModelsWebApiController))))
{
// Access swagger doc first
await ValidationUtils.ValidateSwaggerJson();

// Arrange
var httpClient = HttpClientUtils.GetHttpClient(HttpClientUtils.BaseAddress);
// Verify that the custom web api model can be serialized
var webApiResults = await httpClient.GetJsonAsync<List<SharedModelsSetup.CustomApiModel>>("CustomApiModels");
webApiResults.Should().NotBeNull();
webApiResults.Count.Should().Be(2);
}
}
}

public class SharedModelsSetup
Expand All @@ -61,6 +86,22 @@ public static void Configuration(IAppBuilder appBuilder, Action<SwaggerDocsConfi
config.EnsureInitialized();
}

public static void ConfigurationWithFormatters(IAppBuilder appBuilder, Action<SwaggerDocsConfig> unitTestConfigs, params Type[] targetControllers)
{
var config = new HttpConfiguration
{
IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always
};

config = ConfigureWebApi(config);

config = ConfigureOData(appBuilder, targetControllers, config, unitTestConfigs);

config.Formatters.InsertRange(0, ODataMediaTypeFormatters.Create(new NullSerializerProvider(), new DefaultODataDeserializerProvider()));

config.EnsureInitialized();
}

public static HttpConfiguration ConfigureWebApi(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
Expand All @@ -86,13 +127,76 @@ public static IEdmModel GetEdmModel()
return builder.GetEdmModel();
}

public class NullSerializerProvider : DefaultODataSerializerProvider
{
private readonly NullEntityTypeSerializer _nullEntityTypeSerializer;

public NullSerializerProvider()
{
_nullEntityTypeSerializer = new NullEntityTypeSerializer(this);
}

public override ODataSerializer GetODataPayloadSerializer(IEdmModel model, Type type, HttpRequestMessage request)
{
var serializer = base.GetODataPayloadSerializer(model, type, request);
if (serializer == null)
{
var functions = model.SchemaElements.Where(s => s.SchemaElementKind == EdmSchemaElementKind.Function
|| s.SchemaElementKind == EdmSchemaElementKind.Action);
var isFunctionCall = false;
foreach (var f in functions)
{
// ReSharper disable once UseStringInterpolation
var fname = string.Format("{0}.{1}", f.Namespace, f.Name);
if (request.RequestUri.OriginalString.Contains(fname))
{
isFunctionCall = true;
break;
}
}
// only, if it is not a function call
if (!isFunctionCall)
{
var response = request.GetOwinContext()?.Response;
response?.OnSendingHeaders(state =>
{
((IOwinResponse)state).StatusCode = (int)HttpStatusCode.NotFound;
}, response);
// in case you are NOT using Owin, uncomment the following and comment everything above
// HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.NotFound;
}
return _nullEntityTypeSerializer;
}
return serializer;
}
}

public class NullEntityTypeSerializer : ODataEntityTypeSerializer
{
public NullEntityTypeSerializer(ODataSerializerProvider serializerProvider)
: base(serializerProvider)
{ }
public override void WriteObjectInline(object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)
{
if (graph != null)
{
base.WriteObjectInline(graph, expectedType, writer, writeContext);
}
}
}

public class SharedModel
{
[Key]
public int Id { get; set; }
public string Variation { get; set; }
}

public class CustomApiModel
{
public int PropertyA { get; set; }
}

public class SharedModelsController : ODataController
{
[EnableQuery]
Expand Down Expand Up @@ -123,6 +227,17 @@ public List<SharedModel> Get()
};
return sharedModels;
}

[Route("CustomApiModels")]
public List<CustomApiModel> GetCustomApiModels()
{
var customApiModels = new List<CustomApiModel>
{
new CustomApiModel {PropertyA = 1},
new CustomApiModel {PropertyA = 2}
};
return customApiModels;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ private static Func<MediaTypeFormatter, bool> CanWriteODataType(ODataActionDescr
if (oDataMediaTypeFormatter != null)
{
oDataMediaTypeFormatter.SetInstanceProperty("Request", oDataActionDescriptor.Request);
return mediaTypeFormatter.CanWriteType(returnType);
var mediaType = oDataMediaTypeFormatter.SupportedMediaTypes.FirstOrDefault();
var instanceFormatter = oDataMediaTypeFormatter.GetPerRequestFormatterInstance(returnType,
oDataActionDescriptor.Request, mediaType);
return instanceFormatter.CanWriteType(returnType);
}
return false;
};
Expand All @@ -109,8 +111,10 @@ private static Func<MediaTypeFormatter, bool> CanReadODataType(ODataActionDescri
if (oDataMediaTypeFormatter != null)
{
oDataMediaTypeFormatter.SetInstanceProperty("Request", oDataActionDescriptor.Request);
return mediaTypeFormatter.CanReadType(bodyParameter.ParameterDescriptor.ParameterType);
var mediaType = oDataMediaTypeFormatter.SupportedMediaTypes.FirstOrDefault();
var instanceFormatter = oDataMediaTypeFormatter.GetPerRequestFormatterInstance(bodyParameter.ParameterDescriptor.ParameterType,
oDataActionDescriptor.Request, mediaType);
return instanceFormatter.CanReadType(bodyParameter.ParameterDescriptor.ParameterType);
}
return false;
};
Expand Down

0 comments on commit 50605f5

Please sign in to comment.