是否可以在RedirectToRouteResult中将对象作为路由值发送?

时间:2010-03-01 05:06:46

标签: asp.net-mvc-2 asp.net-mvc-routing

首先,它需要创建一些代码来处理我的应用程序中的任何错误,如下面的代码。

public class HandleSomeErrorAttribute : HandleErrorAttribute
{
    public string ControllerName { get; set; }
    public string ActionName { get; set; }

    public override void OnException(ExceptionContext filterContext)
    {
        base.OnException(filterContext);

        if(filterContext.Result != null)
        {
            var viewResult = filterContext.Result as ViewResult;

            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(
                 new
                 {
                     controller = ControllerName,
                     action = ActionName,
                     errorInfo = "test"
                 }
            ));
        }
    }
}

如果我将test发送为errorInfo值,一切正常。另一方面,如果我发送一些errorInfo对象作为errorInfo值,动作控制器将不会收到任何errorInfo值。它总是为空。

我知道此行为旨在处理用户提交表单时由Web浏览器发送的表单集合中的任何值。因此,它始终只读取字符串值并将其解析为对象。

那么,是否可以这样做?

谢谢,

2 个答案:

答案 0 :(得分:3)

Stackoverflow中搜索一些相关问题之后,我才意识到ASP.NET中的任何重定向操作都会向浏览器发送HTTP 302 code。之后,浏览器将创建新的请求以获取新的URL(可以在HTTP 302 header中找到)。

因此,不可能直接将任何复杂对象(没有序列化)发送到浏览器并命令浏览器将其发送回服务器。虽然有可能,但我认为这样做太傻了。因为您可以使用以下代码调用另一个操作而不向浏览器发送HTTP 302

public class TransferResult : ActionResult
{
    public TransferResult(string controllerName, string actionName, RouteValueDictionary routeValues = null)
    {
        RouteValues = routeValues ?? new RouteValueDictionary();

        if (!string.IsNullOrEmpty(controllerName))
        {
            RouteValues[MvcApplication.ControllerRouteKey] = controllerName;
        }

        if (!string.IsNullOrEmpty(actionName))
        {
            RouteValues[MvcApplication.ActionRouteKey] = actionName;
        }

        if(RouteValues[MvcApplication.ControllerRouteKey] == null)
        {
            throw new ArgumentException(Resources.ControllerNameIsNotFoundInRouteValueDictionary, "controllerName");
        }

        if (RouteValues[MvcApplication.ActionRouteKey] == null)
        {
            throw new ArgumentException(Resources.ActionNameIsNotFoundInRouteValueDictionary, "actionName");
        }
    }

    public TransferResult(RouteValueDictionary routeValues)
        : this(null, null, routeValues)
    {
    }

    public RouteValueDictionary RouteValues { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        var routeData = new RouteData();

        foreach (var item in RouteValues)
        {
            routeData.Values.Add(item.Key, item.Value);   
        }

        var contextWrapper = new HttpContextWrapper(HttpContext.Current);
        var request = new RequestContext(contextWrapper, routeData);

        var controller = ControllerBuilder.Current.GetControllerFactory().CreateController(context.RequestContext, RouteValues[MvcApplication.ControllerRouteKey].ToString());
        controller.Execute(request); 
    }
} 

接下来,我创建了一些句柄错误,用于处理某些错误类型并将其传输到另一个操作控制器。

public class SomeHandleErrorAttribute : HandleErrorAttribute
{
    public SomeHandleErrorAttribute (string controllerName, string actionName)
    {
        ExceptionType = typeof (EntityException);
        ControllerName = controllerName;
        ActionName = actionName;
    }

    public string ControllerName { get; set; }
    public string ActionName { get; set; }

    public override void OnException(ExceptionContext filterContext)
    {
        base.OnException(filterContext);

        if(filterContext.Result != null)
        {
            var routeValue = new RouteValueDictionary
             {
                 {"errorInfo", filterContext}
             };

            filterContext.Result = new TransferResult(ControllerName, ActionName, routeValue);
        }
    }
}

最后,我创建了处理此错误的操作。

public class ErrorController : Controller
{
    public string EntityError(ExceptionContext errorInfo)
    {
        return string.Format("Handle error for {0} ", errorInfo.Exception.Message);
    }
}

答案 1 :(得分:1)

不。重定向将字符串返回给您的浏览器,通知它应该获取的页面(和查询参数)。你可以(而且应该!)在Fiddler看这个。因此,无论你在重定向中放入什么,都必须可以串行化为字符串。