Returning a view with it's model from an ActionFilterAttribute

耗尽温柔 提交于 2019-12-04 10:41:23

I got it to work!

For some odd reason, all I needed to do was to pass on the ViewData to a new ResultView.

Here's the complete code:

public class ErrorLoggingAttribute : ActionFilterAttribute, IExceptionFilter
{
    private String _controllerName, _actionName;
    private Boolean _redirectToGenericView = false;


    public ErrorLoggingAttribute()
    {
    }


    public ErrorLoggingAttribute(String actionName, String controllerName)
    {
        _controllerName = controllerName;
        _actionName = actionName;
        _redirectToGenericView = true;
    }


    void IExceptionFilter.OnException(ExceptionContext ec)
    {
        // log error

        if (_redirectToGenericView)
        {
            ec.Result = new RedirectToRouteResult(new RouteValueDictionary
            {
                {"controller", _controllerName},
                {"action", _actionName}
            });
        }
        else
        {
            ec.Result = new ViewResult
            {
                ViewName = ((RouteData) ec.RouteData).Values["action"].ToString(),
                TempData = ec.Controller.TempData,
                ViewData = ec.Controller.ViewData
            };
        }

        ec.ExceptionHandled = true;
    }
}


Usage


Here's how you would use the attribute on a controller-action, to redirect to the same view (with it's associated model) to enable standard validation-helpers to kick in, when an exception occurs:

[ErrorLogging]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Models.Entities.Message message)
{
    var dc = new Models.DataContext();
    dc.Messages.InsertOnSubmit(message);
    dc.SubmitChanges();

    return RedirectToAction("List", new { id = message.MessageId });
}

And here's how you would use the attribute, to redirect to a generic view, when an exception occurs:

[ErrorLogging("ControllerName", "ViewName")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Models.Entities.Message message)


This is a complete separation of logic. Nothing in the controller but the very basics.

J.W.

Since you inherit from ActionFilterAttribute From OnActionExecuting, you can grab your model.

  public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var model = filterContext.Controller.ViewData.Model as YourModel;

        ...
    }

But there is already HandleError defined in MVC system, why don't you use this one instead of baking your own.

I suggest you read this blog on this issue.

queen3

If your action throws exception, there's no way to pass the model to the view since the model is not probably created yet - or not fully created. That's probably why the result is null. You can't rely on the data after exception was thrown.

But you can pass pass "default" model to your action filter like this:

[ErrorLogging(new EmptyModel())] 
// or to create using Activator
[ErrorLogging(typeof(EmptyModel))]
// or even set view name to be displayed
[ErrorLogging("modelerror", new EmptyModel())]

This way your filter will pass this "error model" that you explicitely set to be displayed when an error happened.

Neal
public class MessageController : Controller
{
  public ActionResult Create()
  {
    return View();
  }

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult Create( Message message )
  {
    try
    {
      // Exceptions for flow control are so .NET 1.0 =)
      // ... your save code here
    }
    catch
    {
      // Ugly catch all error handler - do you really know you can fix the problem?  What id the database server is dead!?!
      return View();
    }
  }
}

The details of the model are already present in modelstate. Any errors should also already be present in modelstate. Your exception handler only needs to handle the case where you want to redirect to a generic error page. Better / more obvious is to throw the attribute away and if you want to redirect in the catch, return a redirect result.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!