簡體   English   中英

在ASP.Net Web表單項目中混合使用ASP.Net MVC自定義路由和部分視圖

[英]Mixing ASP.Net MVC custom routing and partial views in a ASP.Net web forms project

我正在嘗試從以ASP.Net Web表單編寫的CMS緩慢遷移到ASP.Net MVC。 為此,我需要將Web部件(自定義控件)中的功能替換為局部視圖中的功能。 CMS頁面包含許多Web部件,每個Web部件最終都應從MVC部分視圖呈現一些html。 另外,我還需要一種方法來傳遞每個Web部件中設置的參數,並基於這些參數構造局部視圖。 整個目的是將業務邏輯與表示分離,以消除對CMS本身的依賴性。 在此過程中,所有Web部件仍應正常工作。 您對實現此目標的有效方法有任何想法或建議嗎?

這是我的出發點。 我試圖檢索MVC部分視圖作為ASP.Net管道外部的字符串。 為此,我需要使用HttpContext。 由於我沒有這種上下文(我只想使用通過某些接口傳遞的最少的屬性),所以我嘗試創建一個假的。

public class TestController : Controller, ICmsTranslator
{
    public ActionResult Index()
    {
        return View();
    }

    public string RenderAsString(IHttpRequest request, IContext context)
    {
        return RenderRazorViewToString("~/Views/Shared/_TestPartialView.cshtml", new TestModels(), request, context);
    }

    public string RenderRazorViewToString(string viewName, object model, IHttpRequest request, IContext context)
    {
        ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            // create a fake HttpContext
            var fakeRouteData = new RouteData();
            if (!fakeRouteData.Values.ContainsKey("controller") && !fakeRouteData.Values.ContainsKey("Controller"))
            {
                fakeRouteData.Values.Add("controller", GetType().Name
                                                             .ToLower()
                                                             .Replace("controller", ""));
            }
            HttpContextBase offlineContextBase = new OfflineHttpContext(viewName, request, context);
            var offlineControllerContext = new ControllerContext(offlineContextBase, fakeRouteData, this);

            // try to use the fake context to get the partial view
            var viewResult = ViewEngines.Engines.FindPartialView(offlineControllerContext, viewName);
            var viewContext = new ViewContext(offlineControllerContext, viewResult.View, ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(offlineControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }
}




public class OfflineHttpContext : HttpContextBase
{   
    private readonly Hashtable _items = new Hashtable();
    private IPrincipal _user;
    private readonly IHttpRequest _request;
    private readonly IContext _context;
    private readonly string _relativeUrl;

    public OfflineHttpContext(string relativeUrl, IHttpRequest request, IContext context)
    {
        _relativeUrl = relativeUrl;
        _request = request;
        _context = context;
    }

    public override Exception[] AllErrors
    {
        get { return new Exception[0]; }
    }

    public override Cache Cache
    {
        get { return null; }
    }

    public override HttpRequestBase Request
    {
        get
        {
            var serverVariables = new NameValueCollection
                                      {
                                          {"HTTP_HOST", "www.example.com"},
                                          {"APPL_PHYSICAL_PATH", _context.PhysicalPath}
                                      };

            var headers = new NameValueCollection();
            foreach (var header in _request.Headers)
            {
                headers.Add(header.Key, header.Value);
            }
            var formParams = new NameValueCollection();
            var queryStringParams = new NameValueCollection();
            var cookies = new HttpCookieCollection();

            HttpRequestBase httpContext = new OfflineHttpRequest(_relativeUrl, _request.Method, formParams, queryStringParams, cookies, serverVariables, headers);
            return httpContext;
        }
    }

    public override HttpResponseBase Response
    {
        get
        { 
            var httpResponse = new HttpResponse(new StringWriter());
            return new HttpResponseWrapper(httpResponse);
        }
    }

    public override IDictionary Items
    {
        get { return _items; }
    }

    public override IPrincipal User
    {
        get
        {
            if (_user == null)
            {
                // User is logged in
                return new GenericPrincipal(new GenericIdentity("public"), new string[0]);
                // User is logged out
                // return new GenericPrincipal(new GenericIdentity(""), new string[0]);
            }
            return _user;
        }
        set { _user = value; }
    }
}


public class OfflineHttpRequest : HttpRequestBase
{
    private readonly HttpCookieCollection _cookies;
    private readonly NameValueCollection _formParams;
    private readonly NameValueCollection _queryStringParams;
    private readonly NameValueCollection _headers;
    private readonly NameValueCollection _serverVariables;
    private readonly string _relativeUrl;
    private readonly Uri _url;
    private readonly Uri _urlReferrer;
    private readonly string _httpMethod;

    public OfflineHttpRequest(
        string relativeUrl, 
        string httpMethod,
        NameValueCollection formParams, 
        NameValueCollection queryStringParams,
        HttpCookieCollection cookies, 
        NameValueCollection serverVariables, 
        NameValueCollection headers)
    {
        _httpMethod = httpMethod;
        _relativeUrl = relativeUrl;
        _formParams = formParams;
        _queryStringParams = queryStringParams;
        _cookies = cookies;
        _serverVariables = serverVariables;
        _headers = headers;

        //ensure collections are not null
        if (_formParams == null)
        {
            _formParams = new NameValueCollection();
        }
        if (_queryStringParams == null)
        {
            _queryStringParams = new NameValueCollection();
        }
        if (_cookies == null)
        {
            _cookies = new HttpCookieCollection();
        }
        if (_serverVariables == null)
        {
            _serverVariables = new NameValueCollection();
        }
        if (_headers == null)
        {
            _headers = new NameValueCollection();
        }
    }

    public OfflineHttpRequest(
        string relativeUrl,
        string httpMethod, 
        Uri url, 
        Uri urlReferrer,
        NameValueCollection formParams, 
        NameValueCollection queryStringParams,
        HttpCookieCollection cookies, 
        NameValueCollection serverVariables,
        NameValueCollection headers)
        : this(relativeUrl, httpMethod, formParams, queryStringParams, cookies, serverVariables, headers)
    {
        _url = url;
        _urlReferrer = urlReferrer;
        _headers = headers;
    }

    public OfflineHttpRequest(
        string relativeUrl, 
        Uri url, 
        Uri urlReferrer)
        : this(relativeUrl, HttpVerbs.Get.ToString("g"), url, urlReferrer, null, null, null, null, null)
    {
    }

    public override NameValueCollection ServerVariables
    {
        get
        {
            return _serverVariables;
        }
    }

    public override NameValueCollection Form
    {
        get { return _formParams; }
    }

    public override NameValueCollection QueryString
    {
        get { return _queryStringParams; }
    }

    public override NameValueCollection Headers
    {
        get { return _headers; }
    }

    public override HttpCookieCollection Cookies
    {
        get { return _cookies; }
    }

    public override string AppRelativeCurrentExecutionFilePath
    {
        get { return _relativeUrl; }
    }

    public override Uri Url
    {
        get
        {
            return _url;
        }
    }

    public override Uri UrlReferrer
    {
        get
        {
            return _urlReferrer;
        }
    }

    public override string Path
    {
        get
        {
            if (_relativeUrl != null && _relativeUrl.StartsWith("~/"))
            { 
                return _relativeUrl.Remove(0, 1);
            }
            return null;
        }
    }

    public override string PathInfo
    {
        get
        {
            return "";
        }
    }

    public override string PhysicalApplicationPath
    {
        get
        {
            return _serverVariables.Get("APPL_PHYSICAL_PATH");
        }
    }

    public override string PhysicalPath
    {
        get
        {
            var file = "";
            if (Path != null && Path.StartsWith("/"))
            {
                file = Path.Remove(0, 1);
            }
            if (PhysicalApplicationPath != null)
            {
                return PhysicalApplicationPath + "\\" + file.Replace('/', '\\');
            }
            return null;
        }
    }

    public override string HttpMethod
    {
        get
        {
            return _httpMethod;
        }
    }

    public override string UserHostAddress
    {
        get { return null; }
    }

    public override string RawUrl
    {
        get { return null; }
    }

    public override bool IsSecureConnection
    {
        get { return false; }
    }

    public override bool IsAuthenticated
    {
        get
        {
            return false;
        }
    }

    public override string UserAgent
    {
        get
        {
            var agent = _headers.Get("User-Agent") ??
                           "Mozilla/5.0+(compatible;+Googlebot/2.1;++http://www.google.com/bot.html)";
            return agent;
        }
    }

    public override HttpBrowserCapabilitiesBase Browser
    {
        get
        {
            var browser = new HttpBrowserCapabilities
            {
                Capabilities = new Hashtable { { string.Empty, UserAgent } }
            };
            var factory = new BrowserCapabilitiesFactory();
            factory.ConfigureBrowserCapabilities(new NameValueCollection(), browser);

            return new HttpBrowserCapabilitiesWrapper(browser);
        }
    }
}

這是我想在Webforms頁面中呈現PartialViews或ChildActions時使用的MvcUtility類,但是我認為我沒有在UserControl中使用它。

不知道您使用的是哪個MVC版本,但是我知道這可以與MVC 3和Razor Views一起使用。

public static class MvcUtility
{
        public static void RenderPartial(string partialViewName, object model)
        {
            // Get the HttpContext
            HttpContextBase httpContextBase = new HttpContextWrapper(HttpContext.Current);
            // Build the route data, pointing to the Some controller
            RouteData routeData = new RouteData();
            routeData.Values.Add("controller", typeof(Controller).Name);
            // Create the controller context
            ControllerContext controllerContext = new ControllerContext(new RequestContext(httpContextBase, routeData), new Controller());
            // Find the partial view
            IView view = FindPartialView(controllerContext, partialViewName);
            // create the view context and pass in the model
            ViewContext viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary { Model = model }, new TempDataDictionary(), httpContextBase.Response.Output);
            // finally, render the view
            view.Render(viewContext, httpContextBase.Response.Output);
        }

        private static IView FindPartialView(ControllerContext controllerContext, string partialViewName)
        {
            // try to find the partial view
            ViewEngineResult result = ViewEngines.Engines.FindPartialView(controllerContext, partialViewName);
            if (result.View != null)
            {
                return result.View;
            }
            // wasn't found - construct error message
            StringBuilder locationsText = new StringBuilder();
            foreach (string location in result.SearchedLocations)
            {
                locationsText.AppendLine();
                locationsText.Append(location);
            }
            throw new InvalidOperationException(String.Format("Partial view {0} not found. Locations Searched: {1}", partialViewName, locationsText));
        }

        public static void RenderAction(string controllerName, string actionName, object routeValues)
        {
            RenderPartial("RenderActionUtil", new RenderActionVM() { ControllerName = controllerName, ActionName = actionName, RouteValues = routeValues });
        }
    }

要渲染ChildAction,您需要在Shared MVC Views文件夾中有一個局部視圖:

@model YourNamespace.RenderActionVM

@{
    Html.RenderAction(Model.ActionName, Model.ControllerName, Model.RouteValues);
}

和視圖模型:

public class RenderActionVM
{
    public string ControllerName { get; set; }
    public string ActionName { get; set; }
    public object RouteValues { get; set; }
}

最后在您的Webforms頁面調用中,如下所示:

<% MvcUtility.RenderPartial("_SomePartial", null); %> 

<% MvcUtility.RenderAction("SomeController", "SomeAction", new { accountID = Request.QueryString["id"], dateTime = DateTime.Now }); %>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM