I have a custom model binder which pulls an implementation of an interface from a MEF container. It is implemented as follows:

public class PetViewModelBinder : DefaultModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var petId = bindingContext.ValueProvider.GetValue("id");
        var container = controllerContext.HttpContext.Application[MvcApplication.PLUGINS] as CompositionContainer;
        Lazy<IPet, IPetMetadata> pet = null;
        try
        {
            pet = container.GetExport(typeof(IPet), petId);
            var petVM = new Models.PetViewModel(pet);
            bindingContext.ModelMetadata.Model = petVM;

            return base.BindModel(controllerContext, bindingContext);
        }
        catch (Exception)
        {

            throw;
        }
        finally
        {
            container.ReleaseExport(pet);
        }

    }

This works splendidly when MEF has an Export of petId... but returns http status 500 (server error) when an Export does not exist. Error message obfuscation requirements dictate http status 403 (forbidden) should be returned.

What can be done to trap the error, change the response status, and either not return content, or re-route the Action to handle this condition?

有帮助吗?

解决方案

If you want to return a particular http status code you should do that from a controller or action filter.

One way to do this is to return null from your model binder and handle that in your controller. This is a bit coarse however so you won't be able to distinguish between different errors.

Another way to do it would be to throw a specific exception and handle that in your (global) error handling. A customized HandleError action filter could do this:

public class CustomHandleErrorAttribute : HandleErrorAttribute
{
  public int StatusCode { get; set; }

  public override void OnException( ExceptionContext filterContext )
  {
     base.OnException( filterContext );
     if ( StatusCode > 0 )
     {
        filterContext.HttpContext.Response.StatusCode = StatusCode;
     }
  }
}

In your controller, decorate the action with this attribute:

[CustomHandleError( ExceptionType = typeof (NotAllowedException), View = "~/Views/Shared/Error.cshtml",
     StatusCode = 403 )]
public ActionResult Index( FancyModel model )
{
   return View( model );
}

Finally, in your model binder throw a NotAllowedException, which is a custom exception type you'll also need to define.

Note that this will only work on your development setup if you have enabled custom errors in your web.config file.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top