Как переопределить поведение вспомогательного метода Json в базовом контроллере

У меня следующий вопрос:

Ваше приложение будет отвечать на запросы AJAX в формате JSON. Чтобы максимизировать контроль над сериализацией, вы реализуете собственный класс ActionResult.

Вы должны переопределить поведение вспомогательного метода Json в базовом контроллере, чтобы все ответы JSON использовали пользовательский класс результата. Какой класс вы должны наследовать?

Тип ответа — JsonResult. С точки зрения кода мне трудно визуализировать структуру. Когда я прочитал «реализовать» в вопросе, я подумал об интерфейсе, и вот что я придумал:

public class CustAction:ActionResult
{
  //max control over serialization
}
public interface ICustAction:CustAction
{
}

public controller MyController:ICustAction, JsonResult
{
   //override Json() method in here
}

Будет ли приведенный выше код применим к указанному выше вопросу?


person MilesMorales    schedule 29.01.2017    source источник
comment
JsonResult это ActionResult (и использует класс JavaScriptSerializer для преобразования объектов в json)   -  person    schedule 29.01.2017


Ответы (2)


Вы можете переопределить JsonResult и вернуть собственный JsonResult. Например,

СтандартДжсонРезультат

public class StandardJsonResult : JsonResult
{
    public IList<string> ErrorMessages { get; private set; }

    public StandardJsonResult()
    {
        ErrorMessages = new List<string>();
    }

    public void AddError(string errorMessage)
    {
        ErrorMessages.Add(errorMessage);
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        /* If you do not want to serve JSON on HttpGet, uncomment this. */
        /*if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
            string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("GET access is not allowed. Change the JsonRequestBehavior if you need GET access.");
        }*/

        var response = context.HttpContext.Response;
        response.ContentType = string.IsNullOrEmpty(ContentType) ? "application/json" : ContentType;

        if (ContentEncoding != null)
        {
            response.ContentEncoding = ContentEncoding;
        }

        SerializeData(response);
    }

    protected virtual void SerializeData(HttpResponseBase response)
    {
        if (ErrorMessages.Any())
        {
            var originalData = Data;
            Data = new
            {
                Success = false,
                OriginalData = originalData,
                ErrorMessage = string.Join("\n", ErrorMessages),
                ErrorMessages = ErrorMessages.ToArray()
            };

            response.StatusCode = 400;
        }

        var settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Converters = new JsonConverter[]
            {
                new StringEnumConverter(),
            },
        };

        response.Write(JsonConvert.SerializeObject(Data, settings));
    }
}

public class StandardJsonResult<T> : StandardJsonResult
{
    public new T Data
    {
        get { return (T)base.Data; }
        set { base.Data = value; }
    }
}

Базовый контроллер

public abstract class BaseController : Controller
{
    protected StandardJsonResult JsonValidationError()
    {
        var result = new StandardJsonResult();

        foreach (var validationError in ModelState.Values.SelectMany(v => v.Errors))
        {
            result.AddError(validationError.ErrorMessage);
        }
        return result;
    }

    protected StandardJsonResult JsonError(string errorMessage)
    {
        var result = new StandardJsonResult();

        result.AddError(errorMessage);

        return result;
    }

    protected StandardJsonResult<T> JsonSuccess<T>(T data)
    {
        return new StandardJsonResult<T> { Data = data };
    }
}

использование

public class HomeController : BaseController
{
    public ActionResult Index()
    {
        return JsonResult(null, JsonRequestBehavior.AllowGet)

        // Uncomment each segment to test those feature.

        /* --- JsonValidationError Result ---
            {
                "success": false,
                "originalData": null,
                "errorMessage": "Model state error test 1.\nModel state error test 2.",
                "errorMessages": ["Model state error test 1.", "Model state error test 2."]
            }
            */
        ModelState.AddModelError("", "Model state error test 1.");
        ModelState.AddModelError("", "Model state error test 2.");
        return JsonValidationError();

        /* --- JsonError Result ---
            {
                "success": false,
                "originalData": null,
                "errorMessage": "Json error Test.",
                "errorMessages": ["Json error Test."]
            }
        */
        //return JsonError("Json error Test.");

        /* --- JsonSuccess Result ---
            {
                "firstName": "John",
                "lastName": "Doe"
            }
        */
        // return JsonSuccess(new { FirstName = "John", LastName = "Doe"});
    }
}

Источник: Создание строго типизированных приложений AngularJS с помощью ASP.NET MVC 5, Мэтт Ханикатт

person Win    schedule 01.02.2017

person    schedule
comment
Пожалуйста, рассмотрите возможность добавления пояснений к вашему ответу. - person HMD; 20.04.2018