检查开机自检的 MVC 3 路由约束

本文关键字:路由 约束 MVC 开机自检 检查 | 更新日期: 2023-09-27 17:56:51

所以我有一个接受一些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 正文中?

检查开机自检的 MVC 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
);

使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 正文中的版本匹配的路由。