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

发布于 2024-08-23 06:32:31 字数 993 浏览 11 评论 0原文

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

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"
                 }
            ));
        }
    }
}

如果我将测试作为 errorInfo 值发送,则一切正常。另一方面,如果我发送一些 errorInfo 对象作为 errorInfo 值,操作控制器将不会收到任何 errorInfo 值。它始终为空。

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

那么,可以这样做吗?

谢谢

First of all, it needs to create some codes that handle any error in my application like the following code.

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"
                 }
            ));
        }
    }
}

Everything works fine if I send test as errorInfo value. In the other hand, if I send some errorInfo object as errorInfo value, action controller will not receive any errorInfo value. It always is null.

I know this behavior is designed to handle any values in form collection that is sent by web browser when user submits form. So, it always read only string value and parses it to object.

So, is it possible to do that?

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

勿挽旧人 2024-08-30 06:32:31

在我在 Stackoverflow 中搜索一些相关问题后,我才意识到 ASP.NET 中的任何重定向操作都会发送 HTTP 302 代码 到浏览器。之后,浏览器将创建新请求以获取新 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);
    }
}

After I search some related question in Stackoverflow, I just realize that any redirect action in ASP.NET sends HTTP 302 code to browser. After that, browser will create new request to fetch new URL (that can be found in HTTP 302 header).

Therefore, it is impossible to directly send any complex objects (without serialize it) to browser and order browser to send it back to server. Although, it is possible, but I think it is so silly to do that. Because you can use the following code to call another action without send HTTP 302 to browser.

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); 
    }
} 

Next, I create some handle error for handling some error type and transfering it to another action controller.

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);
        }
    }
}

Finally, I create the action for handling this error.

public class ErrorController : Controller
{
    public string EntityError(ExceptionContext errorInfo)
    {
        return string.Format("Handle error for {0} ", errorInfo.Exception.Message);
    }
}
放手` 2024-08-30 06:32:31

没有。重定向会向您的浏览器返回一个字符串,告知其应获取的页面(和查询参数)。您可以(并且应该!)在 Fiddler 中观看此内容。因此,您放入重定向中的任何内容都必须可序列化为字符串或从字符串序列化。

Nope. A redirect returns a string to your browser, informing it of the page (and query parameters) it should fetch. You can (and should!) watch this in Fiddler. So whatever you put into a redirect has to be serializable to/from a string.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文