moved owin config to its own file,

removed predefined route definition in favour of mapping attributes on ApiController classes.
Added JsonpFormatter to ensure cross-domain api web requests will work to this API.
added formatter to HTTPConfiguration for owin config.
This commit is contained in:
chris.watts90@outlook.com 2017-01-30 22:30:58 +00:00
parent 10027d7f22
commit bc3c7a5e31
3 changed files with 195 additions and 9 deletions

View File

@ -0,0 +1,171 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Newtonsoft.Json.Converters;
namespace WindowsDataCenter
{
/// <summary>
/// Handles JsonP requests when requests are fired with text/javascript
/// </summary>
public class JsonpFormatter : JsonMediaTypeFormatter
{
public JsonpFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));
JsonpParameterName = "callback";
}
/// <summary>
/// Name of the query string parameter to look for
/// the jsonp function name
/// </summary>
public string JsonpParameterName { get; set; }
/// <summary>
/// Captured name of the Jsonp function that the JSON call
/// is wrapped in. Set in GetPerRequestFormatter Instance
/// </summary>
private string JsonpCallbackFunction;
public override bool CanWriteType(Type type)
{
return true;
}
/// <summary>
/// Override this method to capture the Request object
/// </summary>
/// <param name="type"></param>
/// <param name="request"></param>
/// <param name="mediaType"></param>
/// <returns></returns>
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, System.Net.Http.HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
var formatter = new JsonpFormatter()
{
JsonpCallbackFunction = GetJsonCallbackFunction(request)
};
// this doesn't work unfortunately
//formatter.SerializerSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
// You have to reapply any JSON.NET default serializer Customizations here
formatter.SerializerSettings.Converters.Add(new StringEnumConverter());
formatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
return formatter;
}
public override Task WriteToStreamAsync(
Type type,
object value,
Stream stream,
HttpContent content,
TransportContext transportContext
)
{
if (string.IsNullOrEmpty(JsonpCallbackFunction))
{
return base.WriteToStreamAsync(type, value, stream, content, transportContext);
}
// write the JSONP pre-amble
var preamble = Encoding.ASCII.GetBytes(JsonpCallbackFunction + "(");
stream.Write(preamble, 0, preamble.Length);
return base.WriteToStreamAsync(type, value, stream, content, transportContext).ContinueWith((innerTask, state) =>
{
if (innerTask.Status == TaskStatus.RanToCompletion)
{
// write the JSONP suffix
var responseStream = (Stream)state;
var suffix = Encoding.ASCII.GetBytes(")");
responseStream.Write(suffix, 0, suffix.Length);
}
}, stream, TaskContinuationOptions.ExecuteSynchronously);
}
//public override Task WriteToStreamAsync(
// Type type,
// object value,
// Stream stream,
// HttpContent content,
// TransportContext transportContext)
//{
// if (string.IsNullOrEmpty(JsonpCallbackFunction))
// return base.WriteToStreamAsync(type, value, stream, content, transportContext);
// StreamWriter writer = null;
// // write the pre-amble
// try
// {
// writer = new StreamWriter(stream);
// writer.Write(JsonpCallbackFunction + "(");
// writer.Flush();
// }
// catch (Exception ex)
// {
// try
// {
// if (writer != null)
// writer.Dispose();
// }
// catch { }
// var tcs = new TaskCompletionSource<object>();
// tcs.SetException(ex);
// return tcs.Task;
// }
// return base.WriteToStreamAsync(type, value, stream, content, transportContext)
// .ContinueWith(innerTask =>
// {
// if (innerTask.Status == TaskStatus.RanToCompletion)
// {
// writer.Write(")");
// writer.Flush();
// }
// }, TaskContinuationOptions.ExecuteSynchronously)
// .ContinueWith(innerTask =>
// {
// writer.Dispose();
// return innerTask;
// }, TaskContinuationOptions.ExecuteSynchronously)
// .Unwrap();
//}
/// <summary>
/// Retrieves the Jsonp Callback function
/// from the query string
/// </summary>
/// <returns></returns>
private string GetJsonCallbackFunction(HttpRequestMessage request)
{
if (request.Method != HttpMethod.Get)
return null;
var query = HttpUtility.ParseQueryString(request.RequestUri.Query);
var queryVal = query[this.JsonpParameterName];
if (string.IsNullOrEmpty(queryVal))
return null;
return queryVal;
}
}
}

View File

@ -69,18 +69,9 @@ namespace WindowsDataCenter
}
}
}
public class StartOwin
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}

View File

@ -0,0 +1,24 @@
using System.Web.Http;
using Owin;
namespace WindowsDataCenter
{
public class StartOwin
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new { id = RouteParameter.Optional }
//);
config.MapHttpAttributeRoutes();
config.Formatters.Insert(0, new JsonpFormatter());
appBuilder.UseWebApi(config);
}
}
}