ASP.NET Core中Server.Transfer的替代方案

时间:2016-09-26 00:08:00

标签: asp.net .net-core asp.net-core-1.0 asp.net-core-webapi

我正在将ASP.NET应用程序迁移到ASP.NET Core,并且他们对HttpServerUtility.Transfer(string path)进行了一些调用。但是,ASP.NET Core中不存在HttpServerUtility

我可以使用替代方案吗?或者Response.Redirect是我唯一的选择吗?

我希望尽可能保持与旧应用程序相同的行为,因为Server.Transfer and Response.Redirect之间存在差异。

4 个答案:

答案 0 :(得分:3)

根据您的情况,我会为您看到一些选项:

  • 返回另一个视图:所以只是HTML。查看Muqeet Khan的答案
  • 返回同一控制器的另一种方法:这也允许执行其他操作的业务逻辑。只需写下return MyOtherAction("foo", "bar")
  • 之类的内容
  • 返回另一个控制器的操作:请参阅Ron C的答案。我对此解决方案有点麻烦,因为它省略了整个中间件,其中包含90%的ASP逻辑。 NET Core(如安全性,cookie,压缩......)。
  • 路由样式中间件:添加类似于路由的中间件。在这种情况下,您的决策逻辑需要在那里进行评估。
  • 中间件堆栈的后期重新运行:您基本上需要重新运行堆栈的大部分内容。我相信这是可能的,但还没有看到解决方案。我已经看过Damian Edwards(用于ASP.NET Core的PM)的演示文稿,他在没有Kestrel / TCPIP用法的情况下托管ASP.NET Core,只是为了在浏览器中本地呈现HTML。那你可以做。但这有很多超载。

建议:转移已经死亡;)。这样的差异是ASP.NET Core存在和性能改进的原因。这对迁移很不利,但对整个平台有利。

答案 1 :(得分:2)

你是对的。 Server.Transfer和Server.Redirect完全不同。 Server.Transfer执行一个新页面并将其结果返回给浏览器,但不通知浏览器它返回了另一个页面。因此,在这种情况下,浏览器URL将显示所请求的原始URL,但内容将来自其他页面。这与执行Server.Redirect完全不同,后者将指示浏览器请求新页面。在这种情况下,浏览器中显示的网址将更改为显示新网址。

要在Asp.Net Core中执行等效的Server.Transfer,您需要更新Request.PathRequest.QueryString属性以指向要传输到的URL,并且需要实例化处理该URL的控制器并调用它的action方法。我在下面提供了完整的代码来说明这一点。

page1.html

 <html>
    <body>
        <h1>Page 1</h1>
    </body>
</html>

page2.html

 <html>
    <body>
        <h1>Page 2</h1>
    </body>
</html>

ExampleTransferController.cs

    using Microsoft.AspNetCore.Diagnostics;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;

    namespace App.Web.Controllers {

        public class ExampleTransferController: Controller {

            public ExampleTransferController() {

            }

            [Route("/example-transfer/page1")]
            public IActionResult Page1() {
                bool condition = true;

                if(condition) {

                    //Store the original url in the HttpContext items
                    //so that it's available to the app.
                    string originalUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}{HttpContext.Request.Path}{HttpContext.Request.QueryString}";
                    HttpContext.Items.Add("OriginalUrl", originalUrl);

                    //Modify the request to indicate the url we want to transfer to
                    string newPath = "/example-transfer/page2";
                    string newQueryString = "";
                    HttpContext.Request.Path = newPath;
                    HttpContext.Request.QueryString = new QueryString(newQueryString);

                    //Now call the action method for that new url
                    //Note that instantiating the controller for the new action method
                    //isn't necessary if the action method is on the same controller as 
                    //the action method for the original request but
                    //I do it here just for illustration since often the action method you
                    //may want to call will be on a different controller.
                    var controller = new ExampleTransferController();
                    controller.ControllerContext = new ControllerContext(this.ControllerContext);
                    return controller.Page2();
                }

                return View();
            }


            [Route("/example-transfer/page2")]
            public IActionResult Page2() {

                string originalUrl = HttpContext.Items["OriginalUrl"] as string;
                bool requestWasTransfered = (originalUrl != null);

                return View();
            }

        }
    }

将原始网址放在HttpContext.Items["OriginalUrl"]中并非绝对必要,但这样做可以让最终页面知道它是否响应转移,如果是,则原始网址是什么。

答案 2 :(得分:0)

我知道这是一个非常古老的问题,但是如果有人使用 Razor Pages 并且正在寻找 Server.Transfer 替代方案(或根据业务规则返回不同视图的方法),您可以使用部分视图。

在这个例子中,我的视图模型有一个名为“UseAlternateView”的属性:

public class TestModel : PageModel
{
    public bool UseAlternateView { get; set; }

    public void OnGet()
    {
        // Here goes code that can set UseAlternateView=true in certain conditions
    }
}

在我的 Razor 视图中,我根据 UseAlternateView 属性的值呈现不同的局部视图:

@model MyProject.Pages.TestModel
@if (Model.UseAlternateView)
{
    await Html.RenderPartialAsync("_View1", Model);
}
else
{
    await Html.RenderPartialAsync("_View2", Model);
}

部分视图(文件“_View1.cshtml”和“_View2.cshtml”)包含如下代码:

@model MyProject.Pages.TestModel
<div>
    Here goes page content, including forms with binding to Model properties
    when necessary
</div>

Obs.:当使用这样的部分视图时,不能使用@Region,因此您可能需要寻找替代方法,以便在母版页的正确位置插入脚本和样式。

答案 3 :(得分:-1)

我相信你正在寻找MVC中的“命名视图”回归。像这样,

1991  182  0.00
1991  194  0.028
1991  202  0.185
1991  211  0.325
1991  219  1.048
1991  240  3.680
1991  254  5.010
1991  260  4.628
1991  273  3.520
1991  288  1.938

以上将返回该特定视图。如果您具有管理视图详细信息的条件,您也可以这样做。