Handle Potentailly dangerous request-MVC-ASP.NET - asp.net-mvc-3

How do I handle potentially dangerous request in MVc?
I am using the following in the global.asax to handle the error, but its not catching those errors.
Its catching other error types.`
else if (httpException is HttpRequestValidationException)
{
routeData.Values.Add("action", "General");
}`
any one done this in MVc?

In mvc, in general HandleErrorAttribute Class is used to handle exceptions and return specific view based on exception type
[HandleError(ExceptionType = typeof(HttpRequestValidationException), View = "RequestIsNotValid")]
public class SomeController : Controller {}
This will redirect to RequestIsNotValid view, when customErrors mode in web.config is 'on' or 'remote'. Of course, during 'remote', it will be shown only to remote users. If you want to test it during development, set customErrors mode= 'on'

I assume you want to allow HTML for certain properties? That will stop the error from being thrown.
In MVC 3, the AllowHtml attribute does the job.
http://davidhayden.com/blog/dave/archive/2011/01/16/AllowHtmlAttributeASPNETMVC3.aspx

Related

MVC5 custom HandleErrorAttribute needs to detect whether to return partial view to ajax call

I've created a custom HandleErrorAttribute in order to implement logging as part of the exception handling. However, unrelated to the logging, I have run into an issue where I need to render a partialview on an Ajax request instead of a JsonResult. I can detect that it is an ajax request but I can't figure out how to determine when it is appropriate to generate a JsonResult or a PartialView. In most instances, a JsonResult is appropriate but in some cases a PartialView is appropriate. Is there a way to determine what the action is expecting from within OnException()?
I was hoping to find a way to detect the required type of response via a property in filterContext or something that would allow me to dynamically determine the expected response type. In all of my research, I could not find anything that would make that possible. So, I dealt with the situation by adding a bool property (defaulting to false) to the custom HandleErrorAttribute class. I then applied this attribute to the method that is responding with a partialView instead of a JsonResult, setting the property value to true. When the property value is true, the OnException() method responds with a partialView instead of a JsonResult.
If there is a better way, please let me know.
I think the following snippets could help you detect the required type of response
protected override void OnException(ExceptionContext filterContext)
{
//Determine the return type of the action
string actionName = filterContext.RouteData.Values["action"].ToString();
Type controllerType = filterContext.Controller.GetType();
var method = controllerType.GetMethod(actionName);
var returnType = method.ReturnType;
if (returnType.Equals(typeof(JsonResult)))
{
}
}

ModelState serialization

I am trying to implement custom validation in Web API. The code in Galloway's video on the subject seems to have changed. I did download the code and the way the create action filter is like this:
public class ValidationActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest,
actionContext.ModelState);
}
}
}
When I post to my api with bad data, this is what is returned:
{"Message":"The request is invalid.","ModelState":{"user":["First name cannot start with A"]}}
Notice how ModelState is not showing individual field causing the error (like user.FirstName).
When I run their application, ModelState does have the field info (comment.Author):
{"Message":"The request is invalid.","ModelState":{"comment.Author":["Author is too long! This was validated on the server."]}}
I have the same action filter and very similar post web api. Why is my error not showing the field level detail?
You probably did set your IncludeErrorDetailPolicy to be 'never' or did set the customErrors in Web.config file to be something else. See this post for details: http://www.jefclaes.be/2012/08/aspnet-web-api-error-detail-policy-now.html
Apparently this was a known issue and has been fixed recently:
http://aspnetwebstack.codeplex.com/workitem/362

Is it possible to RenderPartial a default or error View if the specified View is not found?

I am using MVC3.
I am wondering whether it is possible to render an error View if the specified View is absent.
ie if "MyTableX" is absent:
RenderPartial("MyTableX");
would return "Error.cshtml" as the Partial View, saying something like "Partial View not found" in the page.
MVC got an attribute called [HandleError] which you should set on your BaseController (or on each controller). There is no need to specify any of the options for the attribute.
The problem with [HandleError] is that it can’t handle 404 (not found), thus we need to create a custom error controller and tell ASP.NET to use it (by configuring web.config and creating and ErrorController):
http://blog.gauffin.org/2011/11/how-to-handle-errors-in-asp-net-mvc/#.UTknoxyfjmA
You can do something based off of this - the trick is in getting the view path.
A missing view returns an InvalidOperationException. So we really need to determine if the view is missing or if it's caused from something different. One way is to figure out how to get the IView in the filter, cast it to a RazorView and grab the path off of it - or the 'hacky' way is to do the below code, but actually look for "the view" and "was not found" in the exceptions message. Its ugly, I know, but if you want something that works tonight, thats all I got before I head to bed, otherwise try to get the view info from that filter.
This code from Phil Haack in this link may help in trying to get the path name, a quick test yielded I wasn't able to get the IView because my filterContext.ParentActionViewContext was null.
Retrieve the current view name in ASP.NET MVC?
So I wrote this basic one, but again, anything throwing an InvalidOperationException will cause this.
Also note a missing 'MissingView.cshtml" could cause an infinite loop here (untested assumption)
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class ViewCheckFilterAttribute : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
var exception = filterContext.Exception;
if (exception is System.InvalidOperationException)
{
//ideally here we check to ensure view doesn't exist as opposed
//to something else raising this exception
filterContext.Result = new ViewResult
{
ViewName = "~/Views/Shared/MissingView.cshtml"
};
filterContext.ExceptionHandled = true;
}
}
}

MVC3 What Level Should I Catch Errors

I have a website which is utilzing MVC3. I have an n-tier architecture and I am curious at what level it is best to catch errors.
For isntance let's say I have a Students table I have a StudentRepository with a function such as:
StudentRepository.GetHightestGrade(studentId)
So should I have my Repositry function have a try/catch block - or should I put the try/catch directly into the ActionResult function. OR would I be better served adding in a business class and then my ActionResult function would do something such as
Business.GetHighestGrade(studentId) and that function simply has a try/catch and calls the Repository function?
You should really only wrap methods in try/catch if you are trying to prevent errors from bubbling up the stack. Generally it's best to put the try/catch at the top layers, to shield the users from the errors. Lower layers should generally throw exceptions during exceptional circumstances, you should only try to catch them in higher layers.
You will find your code is much more readable without a ton of try/catch blocks, I personally try to avoid them when I can, and let the MVC3 HandleError filter attribute take care of displaying error messages. However sometimes you may want to retry an operation if it throws an exception, which makes a good try/catch candidate.
Take a look at ELMAH -- using it should help you write code that avoids exceptions in the first place. But you should only explicitly try/catch if you are expecting an exception, and want to take some action in response to it.
it depends on what you wanna do in the catch, do you just wanna fail silently? do you wanna log the error? do you wanna return a view to notify the user that something went wrong?
if you just wanna notify the user, then catch it in the controller.
if you wanna log it, then catch it in your repo, and have your repo do the logging through some logging service, you could use some higher service that does the call catch the error and log it, but that might be an over kill.
you should write a global filter attribute for custom exceptions. Catch all exception over that filter and return to view. Something like that
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;
namespace Filters
{
public sealed class HandleException : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
throw new ArgumentException("filterContext");
else if (typeof(AjaxException).IsInstanceOfType(filterContext.Exception) && !filterContext.ExceptionHandled)
{
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.ContentEncoding = Encoding.UTF8;
filterContext.HttpContext.Response.HeaderEncoding = Encoding.UTF8;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.StatusCode = 400;
filterContext.Result = new ContentResult
{
Content = "Unexpected error",
ContentEncoding = Encoding.UTF8,
};
}
}
}
}
and add this filter to global filter atributes in global.asax
Repository level must have try-catch construction that handle sql exceptions and write errors to Log. If your business logic is complicated and can produce errors or inconsistent states - you should check it and write errors to Log too. If you want to notify user about something gonna wrong (if business logic provide exceptions) - you should use try-catch constructions in your controller actions and use ModelState.AddModelError(), as one of ways to notify user, or use other way to pass info about error into view. And finally you must have class CustomErrorFilter : IExceptionFilter registered in global.asax in Application_Start:
GlobalFilters.Filters.Add(new LoggingFilter());
That filter should write to Log all unhandled errors that occurs on controller level.
Remember about your code provide normal workflow and can provide error workflow (throw exceptions as one of ways to organize error workflow, or return some error codes). You should count on it and handle both workflows.

Returning 404 Error ASP.NET MVC 3

I have tried the following 2 things to have a page return a 404 error:
public ActionResult Index()
{
return new HttpStatusCodeResult(404);
}
public ActionResult NotFound()
{
return HttpNotFound();
}
but both of them just render a blank page. How can I manually return a 404 error from within ASP.NET MVC 3?
If you inspect the response using fiddler, I believe you'll find that the blank page is in fact returning a 404 status code. The problem is no view is being rendered and thus the blank page.
You could get an actual view to be displayed instead by adding a customErrors element to your web.config that will redirect the user to a specific url when a certain status code occurs which you can then handle as you would with any url. Here's a walk-through below:
First throw the HttpException where applicable. When instantiating the exception, be sure to use one of the overloads which takes a http status code as a parameter like below.
throw new HttpException(404, "NotFound");
Then add an custom error handler in your web.config file so that you could determine what view should be rendered when the above exception occurs. Here's an example below:
<configuration>
<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="~/404"/>
</customErrors>
</system.web>
</configuration>
Now add a route entry in your Global.asax that'll handle the url "404" which will pass the request to a controller's action that'll display the View for your 404 page.
Global.asax
routes.MapRoute(
"404",
"404",
new { controller = "Commons", action = "HttpStatus404" }
);
CommonsController
public ActionResult HttpStatus404()
{
return View();
}
All that's left is to add a view for the above action.
One caveat with the above method: according to the book "Pro ASP.NET 4 in C# 2010" (Apress) the use of customErrors is outdated if you're using IIS 7. Instead you should use the httpErrors section. Here's a quote from the book:
But although this setting still works with Visual Studio’s built-in test web
server, it’s effectively been replaced by the <httpErrors> section in IIS 7.x.
I'm successfully using this:
return new HttpNotFoundResult();
throw new HttpException(404, "NotFound"); along with a custom error handler works fine for me.
You should use
// returns 404 Not Found as EmptyResult() which is suitable for ajax calls
return new HttpNotFoundResult();
when you are making AJAX calls to your controllers and don't find any content.
When you are making classic calls to controller actions and returning Views you should use:
// throwing new exception returns 404 and redirects to the view defined in web.config <customErrors> section
throw new HttpException(404, ExceptionMessages.Error_404_ContentNotFound);
You can personalize 404 result with
return new HttpStatusCodeResult(404, "My message");

Resources