Подтвердить что ты не робот

Когда использовать JsonResult над ActionResult

Я не смог найти конкретный ответ на этот вопрос. Я просмотрел сообщения и последующие сообщения из этого вопроса и в другом месте, но все, что я действительно не читал, это то, что JsonResult имеет тип жестко заданного типа, и действительно, т любой прирост производительности.

Если оба результата могут вернуть Json, зачем вам нужно использовать JsonResult для ActionResult.

public ActionResult()
{
    return Json(foo)
}

public JsonResult()
{
    return Json(bar)
}

Может ли кто-нибудь объяснить сценарий, когда ActionResult просто не может выполнить задание и использовать JsonResult должен. Если нет, то почему JsonResult существует в первую очередь.

4b9b3361

Ответ 1

Когда использовать JsonResult над ActionResult

Я обычно возвращаю конкретные результаты (например, JsonResult, ViewResult), и есть мои профи:

Есть некоторые ссылки, в которых люди поддерживают этот подход:

Существует цитата из Pro ASP.NET MVC 3 Framework:

Примечание. Обратите внимание, что тип возвращаемого значения для метода действия в листинг ViewResult. Метод будет компилироваться и работать так же хорошо если бы мы указали более общий тип ActionResult. Фактически, некоторые Программисты MVC будут определять результат каждого метода действий как ActionResult, даже когда они знают, что он всегда будет возвращать больше определенного типа. Мы проявили особую старательность в этой практике в следующие примеры, чтобы дать понять, как вы можете использовать каждый результат типа, но мы склонны быть более расслабленными в реальных проектах.

Я использовал бы ActionResult над конкретным, только если действие должно возвращать разные типы результатов. Но это не такая распространенная ситуация.

Я хотел бы также добавить, что ActionResult является абстрактным классом, поэтому вы не можете просто создать экземпляр этого типа и вернуть его. JsonResult является конкретным, поэтому вы можете создать его экземпляр и вернуться из метода действия. Существует много других типов, полученных из ActionResult, и в основном все они используются для переопределения ExecuteResult.

public abstract class ActionResult
{
    public abstract void ExecuteResult(ControllerContext context);
} 

Этот метод вызывается ControllerActionInvoker и реализует логическую запись данных в объект response.

ControllerActionInvoker не знает о конкретных результатах, поэтому может обрабатывать любой результат, полученный из ActionResult, и реализует ExecuteResult.

В обоих случаях вы возвращаете экземпляр типа JsonResult в свой пример и Json(model), это просто метод Factory, который создает экземпляр JsonResult.

Существует еще один вопрос SO Лучше ли иметь тип данных метода как можно более конкретным или более общим?, где лучшие методы для параметров метода и возврата значения обсуждаются.

Общая идея предоставляет абстрактные типы в качестве параметров, чтобы ваш метод мог обрабатывать более широкий диапазон параметров; возвращает достаточно конкретные типы, чтобы ваши клиенты не могли их отличать или конвертировать.

Ответ 2

Возможно, вы заметили, что имена всех общих типов возврата в контроллере MVC заканчиваются "результатом", и чаще всего большинство действий возвращают ActionResult. Если вы посмотрите на документацию, вы увидите, что несколько, более specalized типов результатов наследуются от абстрактного класса ActionResult. Из-за этого вы можете вернуть ActionResult во все свои действия и даже возвращать разные типы. Пример:

public ActionResult View(int id)
{
    var result = _repository.Find(id);
    if(result == null)
        return HttpNotFound(); //HttpNotFoundResult, which inherits from HttpStatusCodeResult
    return View(result); //ViewResult
}

Все это упрощает возврат другого контента на основе запроса. Итак, почему вы используете JsonResult для ActionResult? Возможно, поэтому нет недоразумений, и вы действительно можете вернуть JSON, возможно, для удобочитаемости или других личных предпочтений.

Ответ 3

На самом деле нет причин использовать JsonResult как возвращаемый тип методов Action. В этом случае лучше использовать абстрактный класс ActionResult, чтобы следовать полиморфным принципам.

Вызывая return Json(value), вы на самом деле вызываете вспомогательный метод класса Controller, который выглядит следующим образом:

protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
{
    return new JsonResult
    {
        Data = data,
        ContentType = contentType,
        ContentEncoding = contentEncoding,
        JsonRequestBehavior = behavior
    };
}

Как мы видим, вспомогательный метод Json в любом случае создает экземпляр JsonResult.

Ответ 4

Он просто придерживается простого принципа Полиморфизм.

Определив сигнатуру метода как возвращающий абстрактный ActionResult, который является базовым типом для JsonResult, ViewResult, ContentResult (и других), вам предоставляется возможность вернуть любой из вышеуказанных типов позволяя реализации действия решить, какой ActionResult вернуться.

Например:

public ActionResult GetData(int id)
{
     var data = .... // some data

     if (Request.AcceptTypes.Contains("json"))
          return Json(data);
     else
          return View(data);
}

В ООП на самом деле является обычной практикой определять возвращаемый тип метода как можно более абстрактным. Вы также можете найти его в .NET BCL, использование IEnumerable<> в Linq, например:

public static IEnumerable<T> Where<T>
                       (
                       this IEnumerable<T> source,
                       Func<T, bool> predicate
                       );

Метод Where() объявляется как возвращающий IEnumerable<T>, так что вы можете вызывать метод для любого типа, реализующего интерфейс IEnumerable<T>, будь то Array, List, HashSet или Dictionary.