我想请求路由到基于特定JSON参数的值不同的动作。
例如,给定以下JSON数据:
{
type: "type1",
type1data: "type1value"
}
和
{
type: "type2",
type2data: "type2value"
}
我希望能够在我的ApiController 2点不同的操作:
void CreateType1(string type1data)
{
// ...
}
void CreateType2(string type2data)
{
//...
}
如何才能像这样做呢?
更新:
我想同样的URL如果可能的话。 喜欢的东西/objects/create
。
我宁愿使用自定义ApiControllerActionSelector。
public class MyActionSelector : ApiControllerActionSelector
{
public override HttpActionDescriptor SelectAction(
HttpControllerContext context)
{
HttpMessageContent requestContent = new HttpMessageContent(
context.Request);
var json = requestContent.HttpRequestMessage.Content
.ReadAsStringAsync().Result;
string type = (string)JObject.Parse(json)["type"];
var actionMethod = context.ControllerDescriptor.ControllerType
.GetMethods(BindingFlags.Instance | BindingFlags.Public)
.FirstOrDefault(m => m.Name == "Create" + type);
if (actionMethod != null)
{
return new ReflectedHttpActionDescriptor(
context.ControllerDescriptor, actionMethod);
}
return base.SelectAction(context);
}
}
这里是模型。 我给它的Abc一个奇怪的名字。
public class Abc
{
public string Type { get; set; }
public string Type1Data { get; set; }
}
下面是操作方法。
public void Createtype1(Abc a)
{
}
最后,外挂的行动选择。
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Services.Replace(typeof(IHttpActionSelector),
new MyActionSelector());
}
}
如果你现在就张贴到http://本地主机:端口/ API / yourapicontroller,取决于JSON在类型字段中的值,操作方法创建*将被选中。
事情是这样的。 为简单起见,这个例子是不正确的异步执行。
using System.Net.Http;
using System.Web.Http;
namespace MyApi.Controllers
{
public class MyType {
public string type {get; set;}
}
public class MyType1 {
public string type {get; set;}
public string type1data {get; set;}
}
public class MyType2 {
public string type {get; set;}
public string type2data {get; set;}
}
public class ObjectsController : ApiController {
//
// api/objects/create
//
public void Create() {
// buffer the content to allow the dual reads below
Request.Content.LoadIntoBufferAsync().Wait();
// get the body as a object so we can access its type property
MyType postedObject = Request.Content.ReadAsAsync<MyType>().Result;
// decide
switch (postedObject.type) {
case "type1":
CreateType1(Request.Content.ReadAsAsync<MyType1>().Result.type1data);
break;
case "type2":
CreateType2(Request.Content.ReadAsAsync<MyType2>().Result.type2data);
break;
default:
// 400 Bad Request would be best, I think.
break;
}
}
private void CreateType1(string type1data) {
// ...
}
private void CreateType2(string type2data) {
// ...
}
}
}