Как переопределить поведение вспомогательного метода 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
}
Будет ли приведенный выше код применим к вышеуказанному вопросу?
2 ответа
Вы можете переопределить JsonResult и вернуть пользовательский JsonResult. Например,
StandardJsonResult
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 от Мэтта Ханикатта
public class customJsonResult : JsonResult
{
//max control over serialization
}
//in the base controller override the Controller.Json helper method:
protected internal override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new customJsonResult {
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
JsonRequestBehavior = behavior
};
}