4

特定の json パラメータの値に基づいて、リクエストをさまざまなアクションにルーティングしたいと考えています。

たとえば、次の json データがあるとします。

{
  type: "type1",
  type1data: "type1value"
}

{
  type: "type2",
  type2data: "type2value"
}

ApiController で 2 つの異なるアクションを実行できるようにしたいと考えています。

void CreateType1(string type1data) 
{ 
  // ... 
}

void CreateType2(string type2data) 
{ 
  //... 
}

このようなことはどのように行うことができますか?

アップデート:

できれば同じURLでお願いします。のようなもの/objects/create

4

2 に答える 2

9

カスタムの 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://localhost:port/api/yourapicontroller に POST すると、JSON の type フィールドの値に応じて、アクション メソッド Create* が選択されます。

于 2013-05-14T14:31:24.677 に答える
0

このようなもの。簡単にするために、この例は適切な非同期実装ではありません。

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) {
            // ...
        }
    }
}
于 2013-05-13T18:57:04.477 に答える