Why ExecuteResult method without body in JsonResult class - asp.net-mvc

In MVC, ActionResult is abstract class having ExecuteResult abstract method.
Of-course, ExecuteResult will be implemented where ActionResult will inherited.
JsonResult is inheriting ActionResult class. So as per the basic rule I expect the implementation of ExecuteResult method in JsonResult class.
See below images.
ActionResult class
JsonResult class
But here no body or concrete implementation of ExecuteResult method in JsonResult class. However the method is overrides but without the body or implementation.
So where is the actual implementation of this abstract method?

That is how your Visual Studio is behaving. We need parituclar settings turned on to see the built-in libraries source code in VS which i can't recall, but you can see the source code for it here which is :
public override void ExecuteResult(ControllerContext context) {
if (context == null) {
throw new ArgumentNullException("context");
}
if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) {
throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed);
}
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType)) {
response.ContentType = ContentType;
}
else {
response.ContentType = "application/json";
}
if (ContentEncoding != null) {
response.ContentEncoding = ContentEncoding;
}
if (Data != null) {
JavaScriptSerializer serializer = new JavaScriptSerializer();
response.Write(serializer.Serialize(Data));
}
}

In visual studio, you cant see any of the implementation details of the built in classes by default. For that install this plugin in your VS

Related

Override ExecuteResult method and set Content-Type

I've inherited a class from ActionResult and then overrided the ExecuteResult method.
public class CustomResult : ActionResult
{
public object Result { get; set; }
public int StatusCode { get; private set; }
public CustomResult(int statusCode, object Result)
{
this.Result = Result;
this.StatusCode = statusCode;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
context.HttpContext.Response.StatusCode = StatusCode;
if (StatusDescription != null)
context.HttpContext.Response.StatusDescription = StatusDescription;
HttpResponseBase Response = context.HttpContext.Response;
Response.Charset = "UTF-8";
Response.ContentType = "application/json";
context.HttpContext.Response.Write(JsonConvert.SerializeObject(this));
}
}
When I return a CustomResult object from the controller, the returned Content-Type to the view is always "text/html" and not "application/json" as setted on CustomResult class.
If I run this application locally all works fine, but when I deploy this one to the Azure App Service the Content-Type is always text/html.
Base on my experience, it could work correctly in the Azure Web App. It works correctly for me even I published the WebApp to Azure environment. If it is possible, please have a try to check it with Fiddler tool.
I've found the solution! I've added this line Response.TrySkipIisCustomErrors = true; to the Response object.

How do I convert an HttpRequest into an HttpRequestBase object?

My problem is the opposite of this:
How do I convert an HttpRequestBase into an HttpRequest object?
In my ASP.NET MVC application I have a method used by many controllers that receive an HttpRequestBase as argument.
Now I have to call that method from another method, that is not an action (it's an nhibernate interceptor). In this second method I could access HttpContext.Current.Request, that is a HttpRequest and I cannot cast it to HttpRequestBase (I thought it was possibile due to the naming ...).
Does someone know in what relationship are this classes and how can I solve my problem?
Thank you.
You'll want to wrap your HttpRequest in a HttpRequestWrapper:
var wrapper = new HttpRequestWrapper(httpRequest);
The HttpRequestWrapper inherits from HttpRequestBase.
This is an another solution which does not require to create a new instance:
var httpRequestBase = myHttpRequest.RequestContext.HttpContext.Request;
In my application I had calls coming from several different places that needed access to the HttpRequestBase. I created this set of extension methods to get and convert from several different Http types into a HttpRequestBase, then used HttpRequestBase as the base type for interface and class methods through the application when I needed access to the request.
public static class RequestExtensions
{
public static HttpRequestBase GetHttpRequestBase(this HttpContext httpContext)
{
if (httpContext == null)
{
throw new ArgumentException("Context is null.");
}
return httpContext.Request.ToHttpRequestBase();
}
public static HttpRequestBase GetHttpRequestBase(this HttpRequestMessage httpRequestMessage)
{
if (httpRequestMessage == null)
{
throw new ArgumentException("Request message is null.");
}
HttpContextWrapper context = null;
if (httpRequestMessage.Properties.ContainsKey("MS_HttpContext"))
{
context = httpRequestMessage.Properties["MS_HttpContext"] as HttpContextWrapper;
}
if (context == null)
{
throw new ArgumentException("Context is null.");
}
return context.Request;
}
public static HttpRequestBase GetHttpRequestBase(this HttpApplication httpApplication)
{
if (httpApplication == null)
{
throw new ArgumentException("Application is null.");
}
return httpApplication.Request.ToHttpRequestBase();
}
public static HttpRequestBase ToHttpRequestBase(this HttpRequest httpRequest)
{
if (httpRequest == null)
{
throw new ArgumentException("Request is null.");
}
return new HttpRequestWrapper(httpRequest);
}
}
I came across several SO answers that helped me build these extensions:
How do I convert an HttpRequestBase into an HttpRequest object?
Convert HttpRequestMessage to HttpRequest
Get the IP address of the remote host
I find the following extension methods useful:
public static HttpContextBase AsBase(this HttpContext context)
{
return new HttpContextWrapper(context);
}
public static HttpRequestBase AsBase(this HttpRequest context)
{
return new HttpRequestWrapper(context);
}
Usage:
HttpContext.Current.AsBase()
HttpContext.Current.Request.AsBase()

Change Default JSON Serializer Used In ASP MVC3 [duplicate]

This question already has answers here:
Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - is it possible?
(7 answers)
Closed 8 years ago.
I have a controller that is returning large JSON objects to jQuery Flot and I was wondering how easy it would be to replace the default JavaScriptSerializer with something faster like the one from ServiceStack.Text.
It would be good if I could change stuff like this using the DependencyResolver, but I suppose if absolutely everything was resolved this was, it could get pretty slow.
your best bet is to inherit from JsonResult class and override Execute method like
public class CustomJsonResult: JsonResult
{
public CustomJsonResult()
{
JsonRequestBehavior = JsonRequestBehavior.DenyGet;
}
public override void ExecuteResult(ControllerContext context) {
if (context == null) {
throw new ArgumentNullException("context");
}
if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) {
throw new InvalidOperationException(MvcResources.JsonRequest_GetNotAllowed);
}
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType)) {
response.ContentType = ContentType;
}
else {
response.ContentType = "application/json";
}
if (ContentEncoding != null) {
response.ContentEncoding = ContentEncoding;
}
if (Data != null) {
CustomJsSerializer serializer = new CustomJsSerializer();
response.Write(serializer.Serialize(Data));
}
}
}
code is taken from JsonResult class of mvc3 and changed this line
JavaScriptSerializer serializer = new JavaScriptSerializer();
to
CustomJsSerializer serializer = new CustomJsSerializer();
you can use this class in action method like
public JsonResult result()
{
var model = GetModel();
return new CustomJsonResult{Data = model};
}
Additionally you can override json method of Controller class in your Base controller like
public class BaseController:Controller
{
protected internal override JsonResult Json(object data)
{
return new CustomJsonResult { Data = data };
}
}
now if you have all your controllers from BaseController then return Json(data) will call your serialization scheme. There are also other overloads of Json method that you may choose to override.
I'm adding this answer simply because I'm using an alternate solution that doesn't require overriding the System.Web.Mvc.Controller class. I add the following extension methods to the System.Web.Mvc.Controller class. The only "benefit" of this solution is that it doesn't require you to change the base class of the code generated Controller classes. Otherwise, it is functionally equivalent to the accepted answer.
public static JsonResult ToJsonResult(this Controller controller,
object target,
string contentType,
Encoding contentEncoding,
JsonRequestBehavior behavior)
{
if (target != null)
{
if (target.GetType().HasAttribute<DataContractAttribute>())
{
return new DataContractJsonResult() { ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior, Data = target };
}
}
return new JsonResult() { ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior, Data = target };
}
public static JsonResult ToJsonResult(this Controller controller, object target)
{
return controller.ToJsonResult(target, null, null, JsonRequestBehavior.DenyGet);
}
public static JsonResult ToJsonResult(this Controller controller, object target, string contentType)
{
return controller.ToJsonResult(target, contentType, null, JsonRequestBehavior.DenyGet);
}
public static JsonResult ToJsonResult(this Controller controller, object target, string contentType, Encoding contentEncoding)
{
return controller.ToJsonResult(target, contentType, contentEncoding, JsonRequestBehavior.DenyGet);
}
public static JsonResult ToJsonResult(this Controller controller, object target, string contentType, JsonRequestBehavior behavior)
{
return controller.ToJsonResult(target, contentType, null, behavior);
}
In my application, I override the default controller and use the JSON.NET serializer if the type has the DataContract attribute. This functionality is encapsulated in the DataContractJsonResult class, which is not included, but is modeled after the class in the accepted answer to this question.

Return special JsonResult in case of Exception occurs

public JsonResult Menu() { // Exception }
I need application not to redirect user to the 404 page, but return special JSON result like { "result":1 }.
I wonder, is there any another solution, not try-catching.
You can implement your own FilterAttribute similar to the HandleErrorAttribute.
The HandleErrorAttribute normally does a redirect when an error occurs, but you could implement a similar attribute that returns a JsonResult. Something like the following will do:
public class CustomHandleErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
filterContext.Result = new JsonResult
{
Data = new { result = 1 },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
filterContext.ExceptionHandled = true;
}
}
And then
[CustomHandleError]
public JsonResult Menu()
{
throw new Exception();
}
I would recommend that you download the MVC source code from CodePlex and inspect the current implementation of HandleErrorAttribute. It is a lot more subtle than my crude implementation above and you may want some of its functionality.

ActionResult helper and different types resolver

Idea is to use same action methods for different types of results
I.E.
/category/details/?resultFormat=json
/category/details/?resultFormat=xml
So to have some kind of ActionResult helper that contains registered pairs of value resolvers
"json", JsonValueResolver
"xml", XmlResolver
etc...is there already solution for this or I have to think some kind of custom resolver?
Automapper has good solution for value resolving. Any ideas?
public class SmartResult : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (context.HttpContext.Request.QueryString["ResultFormat] == "json")
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
context.HttpContext.Response.Write(serializer.Serialize(this.Data));
} else if(context.HttpContext.Request.QueryString["ResultFormat] == "xml")
{
...serialize using xmlserializer
}else{
throw new InvalidOperationException();
}
}
public object Data { get; set; }
}

Resources