文章有點長,但大多是代碼,看看很快的,不要壓力太大。網上有很多關於這兩個方法的區別,都說出了它本質的區別(不看代碼,只看這個結論,就已經足夠了,如果覺得有必要從代碼中得出這個結論,那就繼續往下看),這里從代碼中跟大家說說它們的區別,這兩個擴展方法都是用來加載部分視圖,先說下它們本質上的區別, RenderPartial是直接返回一個視圖,而Partial返回的是視圖的字符串,即一個返回視圖對象,一個返回字符串。內部做了什么呢?接下來詳細介紹。
1.Partial
反編譯工具中對這個擴展類的描述如下:Represents the functionality to render a partial view as an HTML-encoded string.大概意思就是生成一個部分頁作為一個HTML字符串(英語比較好的,再翻譯翻譯,哈哈)。
這個方法是HtmlHelper的擴展方法,這個方法有四個重載,用Reflector工具看下,代碼如下:
public static class PartialExtensions { // Methods public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName); public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName, object model); public static MvcHtmlString Partial(this HtmlHelper htmlHelper,string partialViewName,ViewDataDictionary viewData); public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName, object model, ViewDataDicti onary viewData); }
四個方法都差不多,區別就是傳給它們的參數(不同的參數都是咱們傳給視圖的數據viewData和model),這里就說說第一個和第四個方法,其他都一樣。
(1)兩個參數的Partial
反編譯工具中代碼如下:
public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName) { return htmlHelper.Partial(partialViewName, null, htmlHelper.ViewData); }
第一個參數是擴展方法的語法,這里就不說了。這個方法又調用了一個Partial方法,這個方法就是HtmlHelper中的原生方法了,進去看看它干了什么:
public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName, object model, ViewDataDictionary viewData) { using (StringWriter writer = new StringWriter(CultureInfo.CurrentCulture)) { htmlHelper.RenderPartialInternal(partialViewName, viewData, model, writer, ViewEngines.Engines); return MvcHtmlString.Create(writer.ToString()); } }
很明顯,它用了一個StringWriter,看到這個肯定就知道跟字符串有關了,再說下里面調用的那兩個方法的作用(直接在代碼里講解啦):
internal virtual void RenderPartialInternal(string partialViewName, ViewDataDictionary viewData, object model, TextWriter writer, ViewEngineCollection viewEngineCollection) { if (string.IsNullOrEmpty(partialViewName)) { throw new ArgumentException(MvcResources.Common_NullOrEmpty, "partialViewName"); } ViewDataDictionary dictionary = null; if (model == null) { if (viewData == null) { dictionary = new ViewDataDictionary(this.ViewData);//這些步驟,肯定是在裝填咱們的數據了,下同 } else { dictionary = new ViewDataDictionary(viewData); } } else if (viewData == null) { dictionary = new ViewDataDictionary(model); } else { ViewDataDictionary dictionary2 = new ViewDataDictionary(viewData) {//我現在還不明白這個的作用,了解的同志,求教 Model = model }; dictionary = dictionary2; } ViewContext viewContext = new ViewContext(this.ViewContext, this.ViewContext.View, dictionary, this.ViewContext .TempData, writer); FindPartialView(viewContext, partialViewName, viewEngineCollection).Render(viewContext, writer);
//這個方法就是用來生成視圖的,具體代碼往下看。Render方法就是講FindPartialView方法返回的視圖寫入writer流,詳情繼續看FindPartialView的代碼。
}
再來看下這個代碼,MvcHtmlString.Create(writer.ToString()),看了這個大家就明白了:
//它先調用這個方法
public static MvcHtmlString Create(string value) { return new MvcHtmlString(value); } //然后實例化一個MvcHtmlString,大家看到了,其實它就是將剛才寫入writer中的內容轉為字符串,這里就是說Partial返回的是字符串的原因 public MvcHtmlString(string value) : base(value ?? string.Empty) { this._value = value ?? string.Empty; }
最本質的東西大家都看到了,最后再說下FindPartialView這個方法(直接注釋代碼嘍):
internal static IView FindPartialView(ViewContext viewContext, string partialViewName, ViewEngineCollection viewEngineCollection) { ViewEngineResult result = viewEngineCollection.FindPartialView(viewContext, partialViewName);//從視圖引擎集合中搜索名partialViewName視圖 if (result.View != null)//如果找到該視圖,直接將視圖返回 { return result.View; } StringBuilder builder = new StringBuilder();//這些代碼就不說了,不知所雲,知道的朋友,求教 foreach (string str in result.SearchedLocations) { builder.AppendLine(); builder.Append(str); } throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.Common_PartialViewNotFound, new object[] { partialViewName, builder })); }
執行了FindPartialView之后,會返回一個View,返回View之后執行Render方法,Render方法中應該是將這個返回的視圖寫入writer中(反編譯工具沒得看,原理應該是這樣的)。
(2)四個參數的Partial
直接看代碼,大家就清楚了:
public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName, object model, ViewDataDictionary viewData) { using (StringWriter writer = new StringWriter(CultureInfo.CurrentCulture)) { htmlHelper.RenderPartialInternal(partialViewName, viewData, model, writer, ViewEngines.Engines); return MvcHtmlString.Create(writer.ToString()); } }
代碼就是這樣,是不是感覺似曾相識,其實就跟上面說到的代碼一樣,唯一的區別就是有沒有傳入數據。詳情請看之前附上RenderPartialInternal的代碼,就是裝填數據然后調用生成視圖FindPartialView方法,具體看上面哈,這里就不多說了。
Partial方法說到這里。
2.RenderPartial
反編譯工具中對這個擴展類的描述如下:Provides support for rendering a partial view.意思大概是提供支持生成部分頁的方法。
這個方法是HtmlHelper的擴展方法,這個方法同樣有四個重載,用Reflector工具看下,代碼如下:
public static class RenderPartialExtensions { // Methods public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName); public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, object model); public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, ViewDataDictionary viewData); public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, object model, ViewDataDictionary viewData); }
有沒有感覺跟Partial方法很相似,只是名字不一樣。是的,不一樣的就是它里面調用的方法,這里就說四個擴展方法中的一個(它們調用的是同一個方法,只是有沒有數據的區別),就說下第一個方法代碼如下:
public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName) { htmlHelper.RenderPartialInternal(partialViewName, htmlHelper.ViewData, null, htmlHelper.ViewContext.Writer, ViewEngines.Engines); }
本質的區別就是,在執行了RenderPartialInternal這個方法之后,沒有再執行MvcHtmlString.Create(writer.ToString())這個方法,這就是之前說的Partial是返回字符串,而RenderPartial返回的是視圖的原因。RenderPartialInternal的代碼和Partial方法調用的RenderPartialInternal是一樣的。區別直接上圖比較直觀,如下圖1:
圖1
從圖中可以看出,Partial在生成視圖后,將視圖寫入流中,然后再通過MvcHtmlString.Create方法轉為字符串(具體看Partial中的代碼),而RenderPartial在調用了RenderPartialInternal方法之后就沒有其他操作了(RenderPartialInternal中調用了FinderPartialView方法,此方法中返回View)。
以上就是這兩個方法的區別,不知道有沒有講清楚,當然里面還有一些東西我不清楚的,如果大家也意識到那些東西,可以提出來大家一起聊聊,互相學習,多謝。