Настройка маршрутизации ASP.NET MVC для службы ".json" ".xml" URL-адресов стилей - PullRequest
9 голосов
/ 27 августа 2011

У меня есть поисковый API, над которым я работаю, который должен возвращать результаты поиска в блоке Html (используя стили, определенные клиентом в конце) Я также хотел бы вернуть результаты в Json, для будущих вещей Api, которые мы в конечном итоге будем использовать. В настоящее время маршруты выглядят так:

/api/1/search/json?param1=blah&param2=blah&etc
/api/1/search/html?param1=blah&param2=blah&etc

Для справки, здесь приведен шаблон

Мне нравится внешний вид некоторых API, которые я видел, которые возвращают результаты в разных форматах в зависимости от «расширения», которое они имеют в URL, например:

/api/1/search.json?param1=blah&param2=blah&etc

Однако я не выяснил, как настроить маршрутизацию Mvc в Asp.Net для поддержки этого стиля. Общая маршрутизация в ApiAreaRegistration.cs:

context.MapRoute(
    "Api_default",
    "Api/1/{controller}/{action}/{id}",
    new { action = "Index", id = UrlParameter.Optional });

Я пробовал следующее, определенное выше общего, которое не работает:

//search api
context.MapRoute(
    "searchJson",
    "api/1/{controller}.{action}",
    new { controller = "SearchController" });

Как настроить маршрутизацию для включения URL в формате .format?

Ответы [ 2 ]

9 голосов
/ 27 августа 2011
context.MapRoute(
    "Api_default",
    "{area}/1/{controller}.{format}",
    new { action = "Index", id = UrlParameter.Optional });

это, вероятно, то, что вы хотите.Тогда вы можете просто вернуть разные результаты на основе переданного аргумента.

В контексте Api-области SearchController будет выглядеть так:

public class SearchController : Controller
{
    public ActionResult Index(string format, SearchModel search)
    {
        var results = searchFacade.SearchStuff(search);

        if(format.Equals("xml"))
            return Xml(results); //using an XmlResult or whatever
        if(format.Equals("html"))
            return View(results);
        return Json(results, JsonRequestBehavior.AllowGet);
    }
}
6 голосов
/ 27 августа 2011

Маршрутизация немного сложна, потому что вы вставляете обязательный параметр после необязательного параметра - в общем, Я рекомендую использовать заголовок Accept-Type , который является более RESTful и менее сложным для маршрутизации , Однако с некоторыми клиентами это может быть проблематично.

Маршрутизация должна принимать форму с идентификатором и без идентификатора:

context.MapRoute(
    "Api_default",
    "Api/1/{controller}/{action}/{id}.{format}",
    new { action = "Index" });

context.MapRoute(
    "Api_default_2",
    "Api/1/{controller}/{action}.{format}",
    new { action = "Index" });

Поскольку результаты, как правило, не отличаются, за исключением выходной сериализации, возможно, вы не захотите маршрутизировать другие действия. Пользовательский ActionResult может быть полезным. Таким образом, другая логика сериализации может быть централизованной и легко расширяемой.

public class RestResult<T> : ActionResult
{
    public T Data { get; set; }

    public RestResult(T data)
    {
        Data = data;
    }

    private string SerializeToJson()
    {
        MemoryStream ms = new MemoryStream();
        YourFavouriteJsonSerializer.SerializeToStream(Data, Data.GetType(), ms);
        var temp = Encoding.UTF8.GetString(ms.ToArray());
        return temp;
    }     

    public override void ExecuteResult(ControllerContext context)
    {
        string resultString = string.Empty;
        string resultContentType = string.Empty;

        // alternatively, use the route value dictionary
        // or the accept-type, as suggested.
        var extension = SomeExtensionParserMethod(context.RequestContext.HttpContext.Request.RawUrl);
        string result = string.Empty;
        if (extension == "json")
        {
            result = SerializeJson()
        }
        else if(...)
        // etc

                    context.RequestContext.HttpContext.Response.Write(resultString);
        context.RequestContext.HttpContext.Response.ContentType = resultContentType;
    }
}
...