Skip to content

Instantly share code, notes, and snippets.

@MikeJansen
Created November 5, 2012 13:35
Show Gist options
  • Save MikeJansen/4017214 to your computer and use it in GitHub Desktop.
Save MikeJansen/4017214 to your computer and use it in GitHub Desktop.
Custom IHttpActionSelector
namespace Radar.Common.WebServer.Api.Controllers
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
public class DelegatingActionDescriptor: HttpActionDescriptor
{
private readonly string _actionName;
private readonly HttpActionDescriptor _originalActionDescriptor;
public DelegatingActionDescriptor(string actionName, HttpActionDescriptor originalActionDescriptor)
{
_actionName = actionName;
_originalActionDescriptor = originalActionDescriptor;
}
public override string ActionName
{
get { return _actionName; }
}
public override Task<object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary<string, object> arguments, System.Threading.CancellationToken cancellationToken)
{
return _originalActionDescriptor.ExecuteAsync(controllerContext, arguments, cancellationToken);
}
public override Collection<HttpParameterDescriptor> GetParameters()
{
return _originalActionDescriptor.GetParameters();
}
public override Type ReturnType
{
get { return _originalActionDescriptor.ReturnType; }
}
public override HttpActionBinding ActionBinding
{
get
{
return _originalActionDescriptor.ActionBinding;
}
set
{
_originalActionDescriptor.ActionBinding = value;
}
}
public override bool Equals(object obj)
{
return _originalActionDescriptor.Equals(obj);
}
public override Collection<T> GetCustomAttributes<T>()
{
return _originalActionDescriptor.GetCustomAttributes<T>();
}
public override Collection<FilterInfo> GetFilterPipeline()
{
return _originalActionDescriptor.GetFilterPipeline();
}
public override Collection<IFilter> GetFilters()
{
return _originalActionDescriptor.GetFilters();
}
public override int GetHashCode()
{
return _originalActionDescriptor.GetHashCode();
}
public override ConcurrentDictionary<object, object> Properties
{
get
{
return _originalActionDescriptor.Properties;
}
}
public override IActionResultConverter ResultConverter
{
get
{
return _originalActionDescriptor.ResultConverter;
}
}
public override Collection<HttpMethod> SupportedHttpMethods
{
get
{
return _originalActionDescriptor.SupportedHttpMethods;
}
}
}
}
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using CommonFramework.Container;
using Radar.Common.Server;
using Radar.Common.Server.Container;
using Radar.Common.WebServer.Api;
using Radar.Common.WebServer.Api.Controllers;
using Radar.Common.WebServer.Api.Formatting;
namespace Radar.Api
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
IContainerManager cm = RadarServerContainer.Initialize(ApplicationKeys.ApiKey);
GlobalConfiguration.Configuration.DependencyResolver = new RadarDependencyResolver(cm);
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// <<<<<< ------ HERE ------ >>>>>>
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionSelector), new JsonpCorsActionSelector());
GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonpMediaTypeFormatter());
}
}
}
namespace Radar.Common.WebServer.Api.Controllers
{
using System.Net.Http;
using System.Web.Http.Controllers;
public class JsonpCorsActionSelector : ApiControllerActionSelector
{
private static readonly string HttpMethodQueryParameter = "httpMethod";
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
string httpMethod = controllerContext.Request.RequestUri.ParseQueryString()[HttpMethodQueryParameter];
if (httpMethod != null)
{
HttpRequestMessage originalRequest = controllerContext.Request;
HttpRequestMessage modifiedRequest = new HttpRequestMessage(
new HttpMethod(httpMethod),
originalRequest.RequestUri);
controllerContext.Request = modifiedRequest;
HttpActionDescriptor actualDescriptor = base.SelectAction(controllerContext);
controllerContext.Request = originalRequest;
return new DelegatingActionDescriptor(httpMethod, actualDescriptor);
}
return base.SelectAction(controllerContext);
}
}
}
namespace Radar.Common.WebServer.Api.Formatting
{
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
/// <summary>
///
/// </summary>
/// <remarks>
/// Based on:
/// https://raw.github.com/gist/2967547/2ba629cdfa316348483aca53613d19fc3154f37d/JsonpFormatter.cs
/// http://www.matlus.com/jsonpmediatypeformatter-web-api-jsonp/
/// </remarks>
public class JsonpMediaTypeFormatter : JsonMediaTypeFormatter
{
private readonly string _callbackQueryParameter;
public JsonpMediaTypeFormatter(string callbackQueryParameter)
{
_callbackQueryParameter = callbackQueryParameter ?? "callback";
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));
}
public JsonpMediaTypeFormatter() : this(null) { }
private string CallbackFunction { get; set; }
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
var isJsonp = !string.IsNullOrEmpty(CallbackFunction);
return Task.Factory.StartNew(() =>
{
using (StreamWriter streamWriter = new StreamWriter(writeStream))
{
if (isJsonp)
{
streamWriter.Write(CallbackFunction + "(");
streamWriter.Flush();
}
base.WriteToStreamAsync(type, value, writeStream, content, transportContext).Wait();
if (isJsonp)
{
streamWriter.Write(")");
streamWriter.Flush();
}
}
});
}
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
var formatter = new JsonpMediaTypeFormatter(_callbackQueryParameter)
{
CallbackFunction = GetJsonCallbackFunction(request)
};
return formatter;
}
private string GetJsonCallbackFunction(HttpRequestMessage request)
{
if (request.Method != HttpMethod.Get) return null;
var query = request.RequestUri.ParseQueryString();
var queryVal = query[_callbackQueryParameter];
if (string.IsNullOrEmpty(queryVal)) return null;
return queryVal;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment