Ограничения маршрута MVC 3, которые проверяют POST - PullRequest
1 голос
/ 19 мая 2011

Итак, у меня есть метод, который принимает некоторые данные 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 ]

3 голосов
/ 19 мая 2011

Вместо того, чтобы пытаться проверить версию как ограничение маршрута, почему бы не перейти к одному действию, которое затем проверяет версию для выполнения соответствующей работы?

Я не проверял это, но идея такова:

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
);
0 голосов
/ 19 мая 2011

Сделано 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...