检查POST的MVC 3 Route约束

时间:2011-05-19 13:14:15

标签: c# json asp.net-mvc-3

所以我有一个接受一些JSON数据并将数据绑定到某些变量的方法。路线中只有方法名称,没有别的。

是否可以有一个查看POST数据的路由约束并检查一些变量以确定它是否是正确的路由?

方法:

public ActionResult GetDataV1(string userId)
{
    // Do stuff one way
}

public ActionResult GetDataV2(string userId)
{
    // Do stuff another way
}

路线:

routes.MapRoute(
    "API GetData V1",
    "GetData",
    new { controller = "API", action = "GetDataV1" },
    new { version = new APIVersionRoutingConstraint("1") }
);

routes.MapRoute(
    "API GetData V2",
    "GetData",
    new { controller = "API", action = "GetDataV2" },
    new { version = new APIVersionRoutingConstraint("2") }
);

客户会将{ "version":"1", "userId":"mrjohn" }发布到/GetData,并会收到GetDataV1的回复。 APIVersionRoutingConstraint将确保根据version变量调用正确的方法。

尝试在约束内反序列化请求流是否是一种好习惯?也许最好将版本放在URL中,如/GetData/1和JSON体中的其他变量?

2 个答案:

答案 0 :(得分:3)

为什么不去检查版本以执行适当的工作呢?

我没有测试过这个,但想法是:

public ActionResult GetData(string userId, int version)
{
    switch(version)
    {
        case 1:
            return GetDataV1(userId);
        case 2:
            return GetDataV2(userId);
        // You could always add more cases here as you get more versions, 
        // and still only have the one route
        default:
            // Probably more appropriate to return a result that contains error info,
            // but you get the idea
            throw new ArgumentOutOfRangeException("version");
    }
}

// Made these private since they are called from the public action
private ActionResult GetDataV1(string userId)
{
    // Do stuff one way
}

private ActionResult GetDataV2(string userId)
{
    // Do stuff another way
}

然后你只需要一条路线

routes.MapRoute(
    "GetData",
    "GetData",
    new { controller = "API", action = "GetData" },
    new { version = "\d+" } // Require a numeric version
);

答案 1 :(得分:0)

像这样APIVersionRoutingConstraint

public class APIVersionRoutingConstraint : IRouteConstraint
{
    private string _versionNumber;

    public APIVersionRoutingConstraint(string versionNumber)
    {
        _versionNumber = versionNumber;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        string version = null;

        if (httpContext.Request.ContentType.Contains("application/json"))
        {
            string body = new StreamReader(httpContext.Request.InputStream).ReadToEnd();
            httpContext.Request.InputStream.Position = 0;
            var vals = new JavaScriptSerializer().DeserializeObject(body) as Dictionary<string, object>;
            if (vals.ContainsKey("version"))
                version = vals["version"].ToString();
        }

        // Must have version to pass constraint
        return !string.IsNullOrEmpty(version) && version == _versionNumber;
    }
}

我猜这不是超级高效,但它完成了工作。只使用与POST正文中的版本匹配的路由。