zoukankan      html  css  js  c++  java
  • nopcommerce开源框架技术总结如何实现把controller中的Model的数据传入VIEW中,并生产相应的Html代码

    首先先来看下VIEW代码:

    <div class="Show_h1" id="divHomepageBestSellers">
    
    </div>
     $(document).ready(function () {
                // 通过ajax来实现 以上html代码的显示
    $.ajax({ 
     cache: false, 
     type: "POST",
     url: "@(Url.RouteUrl("HomepageBestSellersJson"))",//这个路由已定义 
     data: { "productThumbPictureSize": 75 },
     success: function (data) {
     $("#divHomepageBestSellers").html(data.html);
     },
     error:function (xhr, ajaxOptions, thrownError){ } }); });
    

      

     

      通过ajax来实现调用HomepageBestSellersJson的action,下面我们来看看它的代码

      [HttpPost]
            public ActionResult HomepageBestSellersJson(int?      productThumbPictureSize, int? orderBy, int? categoryId)
            {
                if (!_catalogSettings.ShowBestsellersOnHomepage || _catalogSettings.NumberOfBestsellersOnHomepage == 0)
                    return Json(new { html = "" });//这一步只是显示的判断,不比理会
    
                var model = GetHomePageBestsellersModel(productThumbPictureSize, orderBy, categoryId);//这是获取model,
                return Json(new { html = this.RenderPartialViewToString("HomepageBestSellers", model), });
            }
    

      下面我们来看看HomepageBestSellersJson的view代码:

    @model HomePageBestsellersModel
    
    @using Nop.Web.Models.Catalog;
    @if (Model.Products.Count > 0)
    {
        int index = 0;
        foreach (var item in Model.Products)
        {
        <dl>	
            <dt><div class="ranks">@(++index)</div><a href="@Url.RouteUrl("Product", new { productId = item.Id })"><img src="@item.DefaultPictureModel.ImageUrl" alt="@item.DefaultPictureModel.AlternateText" title="@item.DefaultPictureModel.Title"/></a></dt>
            <dd>
                <s>@item.ProductPrice.OldPrice</s><br />
                <i class="price">@item.ProductPrice.Price</i><br />
                <a href="@Url.RouteUrl("Product", new { productId = item.Id })" title="@item.DefaultPictureModel.Title">@item.Name</a>
            </dd>
        </dl>
        }
    }
    

      接下来是我讲的重点了,是如何实现这个的

     return Json(new { html = this.RenderPartialViewToString("HomepageBestSellers", model), });
    

      先来看看RenderPartialViewToString这个方法,从下面代码可以看到他是Controller的拓展方法:

    public static class ContollerExtensions
        { 
            public static string RenderPartialViewToString(this Controller controller, string viewName, object model)
            {
                //Original source code: http://craftycodeblog.com/2010/05/15/asp-net-mvc-render-partial-view-to-string/
                if (string.IsNullOrEmpty(viewName))
                    viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
    
                controller.ViewData.Model = model;//传入MODEL数据
    
                using (var sw = new StringWriter())
                {
                    ViewEngineResult viewResult = System.Web.Mvc.ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);//这一步是找到VIEW
                    var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
    //这步是实现把controller中的Model的数据传入VIEW中,并通过viewResult.View.Render生成string代码,这样就完成开始的ajax的调用和实现
                   viewResult.View.Render(viewContext, sw); return sw.GetStringBuilder().ToString(); } } }

      先来看看System.Web.Mvc.ViewEngines.Engines.FindPartialView具体实现和该方法所属类(ThemeableVirtualPathProviderViewEngine )的继承关系,

           public abstract class ThemeableVirtualPathProviderViewEngine : VirtualPathProviderViewEngine

     public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
            {
                var mobileDeviceHelper = EngineContext.Current.Resolve<IMobileDeviceHelper>();
                bool useMobileDevice = mobileDeviceHelper.IsMobileDevice(controllerContext.HttpContext)
                    && mobileDeviceHelper.MobileDevicesSupported()
                    && !mobileDeviceHelper.CustomerDontUseMobileVersion();
    
                string overrideViewName = useMobileDevice ?
                    string.Format("{0}.{1}", partialViewName, _mobileViewModifier)
                    : partialViewName;
          
                ViewEngineResult result = FindThemeablePartialView(controllerContext, overrideViewName, useCache, useMobileDevice);
                // If we're looking for a Mobile view and couldn't find it try again without modifying the viewname
                if (useMobileDevice && (result == null || result.View == null))
                    result = FindThemeablePartialView(controllerContext, partialViewName, useCache, false);
                return result;
            }
    

      

     protected virtual ViewEngineResult FindThemeablePartialView(ControllerContext controllerContext, string partialViewName, bool useCache, bool mobile)
            {
                string[] strArray;
                if (controllerContext == null)
                {
                    throw new ArgumentNullException("controllerContext");
                }
                if (string.IsNullOrEmpty(partialViewName))
                {
                    throw new ArgumentException("Partial view name cannot be null or empty.", "partialViewName");
                }
                var theme = GetCurrentTheme(mobile);
                string requiredString = controllerContext.RouteData.GetRequiredString("controller");
                string str2 = this.GetPath(controllerContext, this.PartialViewLocationFormats, this.AreaPartialViewLocationFormats, "PartialViewLocationFormats", partialViewName, requiredString, theme, "Partial", useCache, mobile, out strArray);
                if (string.IsNullOrEmpty(str2))
                {
                    return new ViewEngineResult(strArray);
                }
                return new ViewEngineResult(this.CreatePartialView(controllerContext, str2), this);
    
            }
        
    
     protected virtual string GetPath(ControllerContext controllerContext, string[] locations, string[] areaLocations, string locationsPropertyName, string name, string controllerName, string theme, string cacheKeyPrefix, bool useCache, bool mobile, out string[] searchedLocations)
            {
                searchedLocations = _emptyLocations;
                if (string.IsNullOrEmpty(name))
                {
                    return string.Empty;
                }
                string areaName = GetAreaName(controllerContext.RouteData);
    
                //little hack to get nop's admin area to be in /Administration/ instead of /Nop/Admin/ or Areas/Admin/
                if (!string.IsNullOrEmpty(areaName) && areaName.Equals("admin", StringComparison.InvariantCultureIgnoreCase))
                {
                    //admin area does not support mobile devices
                    if (mobile)
                    {
                        searchedLocations = new string[0];
                        return string.Empty;
                    }
                    var newLocations = areaLocations.ToList();
                    newLocations.Insert(0, "~/Administration/Views/{1}/{0}.cshtml");
                    newLocations.Insert(0, "~/Administration/Views/{1}/{0}.vbhtml");
                    newLocations.Insert(0, "~/Administration/Views/Shared/{0}.cshtml");
                    newLocations.Insert(0, "~/Administration/Views/Shared/{0}.vbhtml");
                    areaLocations = newLocations.ToArray();
                }
    
                bool flag = !string.IsNullOrEmpty(areaName);
                List<ViewLocation> viewLocations = GetViewLocations(locations, flag ? areaLocations : null);
                if (viewLocations.Count == 0)
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Properties cannot be null or empty.", new object[] { locationsPropertyName }));
                }
                bool flag2 = IsSpecificPath(name);
                string key = this.CreateCacheKey(cacheKeyPrefix, name, flag2 ? string.Empty : controllerName, areaName, theme);
                if (useCache)
                {
                    var cached = this.ViewLocationCache.GetViewLocation(controllerContext.HttpContext, key);
                    if (cached != null)
                    {
                        return cached;
                    }
                }
                if (!flag2)
                {
                    return this.GetPathFromGeneralName(controllerContext, viewLocations, name, controllerName, areaName, theme, key, ref searchedLocations);
                }
                return this.GetPathFromSpecificName(controllerContext, name, key, ref searchedLocations);
            }
    

      还有一些具体的方法没有给出,希望大家去看看nop的源码会有很大的收获的,也许我讲的不怎么清洗,但是我希望大家能够理解大致的流程,这功能对我们来说是很有用的,阿门!

  • 相关阅读:
    【c++】龟兔赛跑问题
    【2016.3.21】关于字符串的一点总结
    程序员面试宝典(第五版)里的错误
    团队作业_总结_RTCSD2017
    团队作业_一周二周_RTCSD2017
    第三次作业_RTCSD2017
    第二次作业_RTCSD
    分析Demo1闪灯例程里的main.c
    第一次作业_RTCSD2017
    约束与自由
  • 原文地址:https://www.cnblogs.com/EntityFramework/p/2921751.html
Copyright © 2011-2022 走看看