سؤال

تستخدم بعض المواقع التي أقوم ببرمجتها كلا من ASP.NET MVC وWebForms.

لدي عرض جزئي وأريد تضمينه داخل نموذج ويب.يحتوي العرض الجزئي على بعض التعليمات البرمجية التي يجب معالجتها في الخادم، لذا فإن استخدام Response.WriteFile لا يعمل.يجب أن تعمل مع تعطيل جافا سكريبت.

كيف يمكنني أن أفعل هذا؟

هل كانت مفيدة؟

المحلول

وكان لي نظرة على مصدر MVC لأرى إن كنت أستطيع معرفة كيفية القيام بذلك. ويبدو أن هناك اقتران وثيق جدا بين السياق تحكم وجهات النظر، عرض البيانات والبيانات التوجيه وأتش تي أم أل تقديم الأساليب.

وفي الأساس من أجل تحقيق ذلك تحتاج إلى إنشاء كل عنصر من هذه العناصر إضافية. بعضها بسيط نسبيا (مثل عرض البيانات) ولكن بعضها قليلا أكثر تعقيدا - على سبيل المثال سوف تنظر البيانات التوجيه الصفحة لدت WebForms الحالي بأن يتجاهلك الآخرون

والمشكلة الكبرى يبدو أن يكون HttpContext - صفحات MVC تعتمد على HttpContextBase (بدلا من HttpContext مثل لدت WebForms تفعل) وفي حين أن كلا تنفيذ IServiceProvider انهم لا علاقة. قدم مصممو MVC قرارا متعمدا عدم تغيير لدت WebForms القديمة إلى استخدام قاعدة السياق جديدة، ولكن لأنها توفر المجمع.

وهذا يعمل ويتيح لك إضافة نظرة جزئية إلى نموذج ويب:

public class WebFormController : Controller { }

public static class WebFormMVCUtil
{

    public static void RenderPartial( string partialName, object model )
    {
        //get a wrapper for the legacy WebForm context
        var httpCtx = new HttpContextWrapper( System.Web.HttpContext.Current );

        //create a mock route that points to the empty controller
        var rt = new RouteData();
        rt.Values.Add( "controller", "WebFormController" );

        //create a controller context for the route and http context
        var ctx = new ControllerContext( 
            new RequestContext( httpCtx, rt ), new WebFormController() );

        //find the partial view using the viewengine
        var view = ViewEngines.Engines.FindPartialView( ctx, partialName ).View;

        //create a view context and assign the model
        var vctx = new ViewContext( ctx, view, 
            new ViewDataDictionary { Model = model }, 
            new TempDataDictionary() );

        //render the partial view
        view.Render( vctx, System.Web.HttpContext.Current.Response.Output );
    }

}

وبعد ذلك في نموذج ويب الخاص بك يمكنك القيام بذلك:

<% WebFormMVCUtil.RenderPartial( "ViewName", this.GetModel() ); %>

نصائح أخرى

لقد استغرق الأمر بعض الوقت، لكنني وجدت حلاً رائعًا.يعمل حل Keith مع الكثير من الأشخاص، ولكنه في مواقف معينة ليس هو الأفضل، لأنك في بعض الأحيان تريد أن يتم تطبيقك انتقل من خلال عملية وحدة التحكم لتقديم وجهة النظر، و يعرض حل Keith العرض باستخدام نموذج محدد أقدم هنا حلاً جديدًا من شأنه تشغيل العملية العادية.

الخطوات العامة:

  1. إنشاء فئة المرافق
  2. قم بإنشاء وحدة تحكم وهمية مع عرض وهمي
  3. في الخاص بك aspx أو master page, ، قم باستدعاء طريقة الأداة المساعدة لتقديم تمرير جزئي لوحدة التحكم، وعرض النموذج المراد عرضه (ككائن) وإذا كنت بحاجة إلى ذلك،

دعونا نتحقق من ذلك عن كثب في هذا المثال

1) إنشاء فئة تسمى MVCUtility وإنشاء الطرق التالية:

    //Render a partial view, like Keith's solution
    private static void RenderPartial(string partialViewName, object model)
    {
        HttpContextBase httpContextBase = new HttpContextWrapper(HttpContext.Current);
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Dummy");
        ControllerContext controllerContext = new ControllerContext(new RequestContext(httpContextBase, routeData), new DummyController());
        IView view = FindPartialView(controllerContext, partialViewName);
        ViewContext viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary { Model = model }, new TempDataDictionary(), httpContextBase.Response.Output);
        view.Render(viewContext, httpContextBase.Response.Output);
    }

    //Find the view, if not throw an exception
    private static IView FindPartialView(ControllerContext controllerContext, string partialViewName)
    {
        ViewEngineResult result = ViewEngines.Engines.FindPartialView(controllerContext, partialViewName);
        if (result.View != null)
        {
            return result.View;
        }
        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));
    }       

    //Here the method that will be called from MasterPage or Aspx
    public static void RenderAction(string controllerName, string actionName, object routeValues)
    {
        RenderPartial("PartialRender", new RenderActionViewModel() { ControllerName = controllerName, ActionName = actionName, RouteValues = routeValues });
    }

أنشئ فئة لتمرير المعلمات، وسأسميها هنا RendeActionViewModel (يمكنك إنشاء فئة MvcUtility في نفس الملف)

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

2) الآن قم بإنشاء وحدة تحكم باسم DummyController

    //Here the Dummy controller with Dummy view
    public class DummyController : Controller
    {
      public ActionResult PartialRender()
      {
          return PartialView();
      }
    }

قم بإنشاء طريقة عرض وهمية تسمى PartialRender.cshtml (عرض الحلاقة) ل DummyController مع المحتوى التالي، لاحظ أنه سيتم تنفيذ إجراء عرض آخر باستخدام مساعد Html.

@model Portal.MVC.MvcUtility.RenderActionViewModel
@{Html.RenderAction(Model.ActionName, Model.ControllerName, Model.RouteValues);}

3) الآن فقط ضع هذا في ملفك MasterPage أو aspx الملف، لتقديم العرض الذي تريده بشكل جزئي.لاحظ أن هذه إجابة رائعة عندما يكون لديك مشاهدات متعددة لشفرات الحلاقة وتريد مزجها مع مشاهداتك MasterPage أو aspx الصفحات.(لنفترض أن لدينا عرضًا جزئيًا يسمى تسجيل الدخول لصفحة وحدة التحكم الرئيسية).

    <% MyApplication.MvcUtility.RenderAction("Home", "Login", new { }); %>

أو إذا كان لديك نموذج للانتقال إلى الإجراء

    <% MyApplication.MvcUtility.RenderAction("Home", "Login", new { Name="Daniel", Age = 30 }); %>

وهذا الحل عظيم لا يستخدم مكالمة اياكس, ، والتي لن تسبب أ تقديم متأخر لوجهات النظر المتداخلة، فإنه لا يقوم بإنشاء طلب WebRequest جديد لذلك لن يجلب لك جلسة جديدة, ، وهو سوف يقوم بمعالجة طريقة استرداد ActionResult للمنظر الذي تريده يعمل دون تمرير أي نموذج

شكرا ل استخدام MVC RenderAction داخل نموذج الويب

والطريقة الأكثر وضوحا سيكون عبر AJAX

وشيء من هذا القبيل (باستخدام مسج)

<div id="mvcpartial"></div>

<script type="text/javascript">
$(document).load(function () {
    $.ajax(
    {    
        type: "GET",
        url : "urltoyourmvcaction",
        success : function (msg) { $("#mvcpartial").html(msg); }
    });
});
</script>

وهذا شيء عظيم، وذلك بفضل!

وأنا باستخدام MVC 2 على .NET Framework 4، الأمر الذي يتطلب TextWriter يحصل تمريرها إلى ViewContext، ولذلك عليك أن تمر في httpContextWrapper.Response.Output كما هو مبين أدناه.

    public static void RenderPartial(String partialName, Object model)
    {
        // get a wrapper for the legacy WebForm context
        var httpContextWrapper = new HttpContextWrapper(HttpContext.Current);

        // create a mock route that points to the empty controller
        var routeData = new RouteData();
        routeData.Values.Add(_controller, _webFormController);

        // create a controller context for the route and http context
        var controllerContext = new ControllerContext(new RequestContext(httpContextWrapper, routeData), new WebFormController());

        // find the partial view using the viewengine
        var view = ViewEngines.Engines.FindPartialView(controllerContext, partialName).View as WebFormView;

        // create a view context and assign the model
        var viewContext = new ViewContext(controllerContext, view, new ViewDataDictionary { Model = model }, new TempDataDictionary(), httpContextWrapper.Response.Output);

        // render the partial view
        view.Render(viewContext, httpContextWrapper.Response.Output);
    }

وهنا نهجا مماثلا الذي تم العمل بالنسبة لي. وتتمثل الاستراتيجية في تقديم نظرة جزئية إلى سلسلة، ثم الإخراج الذي في صفحة نموذج ويب.

 public class TemplateHelper
{
    /// <summary>
    /// Render a Partial View (MVC User Control, .ascx) to a string using the given ViewData.
    /// http://www.joeyb.org/blog/2010/01/23/aspnet-mvc-2-render-template-to-string
    /// </summary>
    /// <param name="controlName"></param>
    /// <param name="viewData"></param>
    /// <returns></returns>
    public static string RenderPartialToString(string controlName, object viewData)
    {
        ViewDataDictionary vd = new ViewDataDictionary(viewData);
        ViewPage vp = new ViewPage { ViewData = vd};
        Control control = vp.LoadControl(controlName);

        vp.Controls.Add(control);

        StringBuilder sb = new StringBuilder();
        using (StringWriter sw = new StringWriter(sb))
        {
            using (HtmlTextWriter tw = new HtmlTextWriter(sw))
            {
                vp.RenderControl(tw);
            }
        }

        return sb.ToString();
    }
}

في لcodebehind الصفحة، يمكنك القيام به

public partial class TestPartial : System.Web.UI.Page
{
    public string NavigationBarContent
    {
        get;
        set;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        NavigationVM oVM = new NavigationVM();

        NavigationBarContent = TemplateHelper.RenderPartialToString("~/Views/Shared/NavigationBar.ascx", oVM);

    }
}

ووفي الصفحة سيكون لديك الوصول إلى المحتويات المقدمة

<%= NavigationBarContent %>

وعلى أمل أن يساعد!

وهذا الحل يأخذ نهجا مختلفا. فإنه يعرف System.Web.UI.UserControl التي يمكن أن يكون مكان على أي نموذج ويب وتهيئتها لعرض المحتوى من أي URL ... بما في ذلك وجهة نظر MVC جزئي. هذا النهج هو مماثل لمكالمة AJAX لHTML في تلك المعلمات (إن وجدت) وتعطى عن طريق سلسلة الاستعلام URL.

أولا، تحديد عنصر تحكم مستخدم في الملفات 2:

و/controls/PartialViewControl.ascx ملف

<%@ Control Language="C#" 
AutoEventWireup="true" 
CodeFile="PartialViewControl.ascx.cs" 
Inherits="PartialViewControl" %>

و/controls/PartialViewControl.ascx.cs:

public partial class PartialViewControl : System.Web.UI.UserControl {
    [Browsable(true),
    Category("Configutation"),
    Description("Specifies an absolute or relative path to the content to display.")]
    public string contentUrl { get; set; }

    protected override void Render(HtmlTextWriter writer) {
        string requestPath = (contentUrl.StartsWith("http") ? contentUrl : "http://" + Request.Url.DnsSafeHost + Page.ResolveUrl(contentUrl));
        WebRequest request = WebRequest.Create(requestPath);
        WebResponse response = request.GetResponse();
        Stream responseStream = response.GetResponseStream();
        var responseStreamReader = new StreamReader(responseStream);
        var buffer = new char[32768];
        int read;
        while ((read = responseStreamReader.Read(buffer, 0, buffer.Length)) > 0) {
            writer.Write(buffer, 0, read);
        }
    }
}

وثم إضافة عنصر تحكم المستخدم إلى صفحة نموذج الويب الخاص بك:

<%@ Page Language="C#" %>
<%@ Register Src="~/controls/PartialViewControl.ascx" TagPrefix="mcs" TagName="PartialViewControl" %>
<h1>My MVC Partial View</h1>
<p>Below is the content from by MVC partial view (or any other URL).</p>
<mcs:PartialViewControl runat="server" contentUrl="/MyMVCView/"  />

وFWIW، وأنا بحاجة إلى أن تكون قادرة على تقديم نظرة جزئية حيوي من التعليمات البرمجية نماذج الويب الحالية، وأدخله في الجزء العلوي من عنصر تحكم معين. لقد وجدت هذا الجواب كيث يمكن أن تتسبب في نظرة جزئية سيتم عرضها خارج العلامة <html />.

وعن طريق الإجابات من كيث وHilarius للإلهام، بدلا من تقديم مباشرة إلى HttpContext.Current.Response.Output، أنا قدمت سلسلة أتش تي أم أل، وأضاف أنها LiteralControl إلى الرقابة ذات الصلة.

في فئة المساعد ثابتة:

    public static string RenderPartial(string partialName, object model)
    {
        //get a wrapper for the legacy WebForm context
        var httpCtx = new HttpContextWrapper(HttpContext.Current);

        //create a mock route that points to the empty controller
        var rt = new RouteData();
        rt.Values.Add("controller", "WebFormController");

        //create a controller context for the route and http context
        var ctx = new ControllerContext(new RequestContext(httpCtx, rt), new WebFormController());

        //find the partial view using the viewengine
        var view = ViewEngines.Engines.FindPartialView(ctx, partialName).View;

        //create a view context and assign the model
        var vctx = new ViewContext(ctx, view, new ViewDataDictionary { Model = model }, new TempDataDictionary(), new StringWriter());

        // This will render the partial view direct to the output, but be careful as it may end up outside of the <html /> tag
        //view.Render(vctx, HttpContext.Current.Response.Output);

        // Better to render like this and create a literal control to add to the parent
        var html = new StringWriter();
        view.Render(vctx, html);
        return html.GetStringBuilder().ToString();
    }

في الدرجة الدعوة:

    internal void AddPartialViewToControl(HtmlGenericControl ctrl, int? insertAt = null, object model)
    {
        var lit = new LiteralControl { Text = MvcHelper.RenderPartial("~/Views/Shared/_MySharedView.cshtml", model};
        if (insertAt == null)
        {
            ctrl.Controls.Add(lit);
            return;
        }
        ctrl.Controls.AddAt(insertAt.Value, lit);
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top