对于这种情况,正确的模型绑定架构是什么?

时间:2014-04-02 17:10:21

标签: asp.net asp.net-mvc asp.net-mvc-3 model-binding

我用WebApi替换了一些旧的Web服务代码,我遇到的情况是代码用来做这样的事情:

If Request.QueryString("value") = 1 Then
    {do first action}
Else
    {do second action}
End If

每个操作都完全不同,每个操作都有一组独立的其他查询字符串参数。

在我的新版本中,我将其建模为:

Public Function FirstAction(model as FirstActionModel) As HttpResponseMessage

Public Function SecondAction(model as SecondActionModel) As HttpResponseMessage

问题是传入的请求只会调用/api/actions?actiontype=1&params.../api/actions?actiontype=2&params...,并且参数不同。

我希望能够将actiontype=1的请求路由到FirstAction,将actiontype=2路由到SecondAction。但是我不能使用路由,因为重要的值在查询字符串中,而不是路径。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

正如我在评论中提到的,您可以使用IHttpActionSelector来实现这一目标。但是,不是直接实现接口,而是可以继承默认实现。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Http.Controllers;

namespace WebApplication1
{
    public class CustomHttpActionSelector : ApiControllerActionSelector 
    {
        public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
        {
            var urlParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query);
            var actionType = urlParam["actiontype"];
            if (actionType == null)
                return base.SelectAction(controllerContext);

            MethodInfo methodInfo;
            if (actionType.ToString() == "1")
                methodInfo = controllerContext.ControllerDescriptor.ControllerType.GetMethod("Action1");
            else
                methodInfo = controllerContext.ControllerDescriptor.ControllerType.GetMethod("Action2");

            return new ReflectedHttpActionDescriptor(controllerContext.ControllerDescriptor, methodInfo);
        }
    }
}

要注册,您需要在WebApiConfig.cs文件中添加以下行:

config.Services.Replace(typeof(IHttpActionSelector), new CustomHttpActionSelector());

在你的控制器中,你要添加两个方法Action1和Action2:

    public string Action1(string param)
    {
        return "123";
    }

    public string Action2(string param)
    {
        return "345";
    }