2012-05-30 32 views
2

我們正在將大型WebForms應用程序轉移到MVC。UserControls的MVC替代品

在WebForms應用程序中,我們有一些可重用的控件(.ascx)。例如,當您鍵入時,顯示用戶名建議的文本框。該控件向頁面添加一些JS/CSS,具有一些服務器端邏輯和自定義屬性(如SelectedUserID)。

MVC應用程序應該如何?如何將這些東西封裝到MVC應用程序中的一個可重用實體中?也許是部分觀點?但是你不能從部分視圖(比較好的是,檢查它還沒有被添加)向頁面的<head>添加JS/CSS ...另外,如何在部分視圖中返回類似所提及的SelectedUserID之類的內容視圖?

要改寫這個問題 - 你將如何在MVC應用程序中實現這樣的控制?

PS。我知道你仍然可以在MVC應用程序中使用.ascx用戶控件,但它似乎是一種「hacky/legacy」方式。什麼是「合法」選項?

+0

所有我能想到的是編寫一個自定義的jQuery插件,並做類似$(「input#myTextBox」)。makeSuggestable(); – Alex

回答

4

迄今爲止發現的最佳解決方案是Razor聲明助手。它們非常合身。

@helper UserTextBox() { 
    <input type="text" /> 

    <!--my own helper that registers scripts--> 
    @Html.AddJS("../js/myscript.js") 
} 

相關問題:Razor: Declarative HTML helpers

相關注意事項:不能使用@Html幫手聲明幫手內,但有一個變通方法:https://stackoverflow.com/a/5557503/56621

1

那麼,你不能有「自動」包含css/js的東西。這是用戶必須添加到頁面(主/佈局或當前頁面)的東西。但總的來說,人們會創建一個Html Helper。不要期望這些是複雜的系統(比如asp.net時代的巨大網格),但是你可以用它們做很多事情。

是的,對於簡單的事情,部分頁面可能更容易。更簡單的可能是編輯器或顯示模板。

但是,一般來說,現在MVC的大多數「控件」都是基於jQuery的。

一個簡短的視頻,請訪問:http://www.asp.net/mvc/videos/mvc-2/how-do-i/how-do-i-create-a-custom-html-helper-for-an-mvc-application

不要被誘惑,包括在這些機制您的JavaScript。雖然它可能適用於單個控件,但如果您在頁面上有多個控件,您將獲得重複的css/js。

+0

對於不包含JavaScript這種方式+1。其實我更喜歡讓頁面決定包含哪些JavaScript而不是PartialViews。 –

1

我會將js/css添加到主佈局,然後編寫一個html助手來呈現您的自定義控件。

許多在aspnet mvc中使用jquery的控件都是這樣工作的。

看看這個控制here

0

1)定製的JS/CSS,你可以使用的部分是這樣的:

//代碼鑑於layoutpage

@section someName 
{ 
    ... 
} 

//代碼

@if (IsSectionDefined("someName")) 
    { 
     @RenderSection("someName") 
    } 

2)我最好這樣做:

  • 創建模型SelectedUser與Id屬性
  • 這種模式
  • 一個SelectedUser對象添加到任何模式,它需要它
+0

這需要剃刀 – Alex

+1

@jitbit如果你打算做MVC,我強烈推薦使用Razor。 –

+0

我同意@ErikPhilips。 –

4

你的問題是相當廣泛的創建模板。我所有的評論/答案將在Razor。在我看來,如果你要切換到MVC,你還可以使用Razor。有很多很好的理由可以改變,但我會說我的首選對於任何正在遷移的人來說,最好的理由是兩倍;第一個剃刀允許我放棄一些關於編程如何與webforms協作的壞習慣,並且在同一個莊園中,它迫使我重寫我的代碼,而不是嘗試複製和粘貼並將原始代碼更改爲在MVC中工作。

該控件向頁面添加一些JS/CSS,具有一些服務器端邏輯和自定義屬性。 MVC應用程序應該如何?

這是一個漂亮的religious software問題。有很多方法可以做到這一點。

因此,到我如何在MVC中添加JS/CSS的宗教觀點。包含服務器端的一種方法是在佈局/主模板中創建一個區域。

查看/ _ViewStart.cshtml

@{ 
    Layout = "~/Views/Shared/Layout.cshtml"; 
} 

查看/共享/ Layout.cshtml

<!doctype html> 
    <head> 
    <link href="/Styles/Global.css" rel="stylesheet" type="text/css" /> 
    @RenderSection("Styles", required: false) 
    <script src="/Scripts/Global.js" type="text/javascript"></script> 
    @RenderSection("Scritps", required: false) 

這將允許每個視圖任選地(因爲required=false)添加任何樣式或腳本使用RenderSecion代碼。

查看/主頁/ Index.cshtml

@section Styles { 
    <link href="/Styles/Home/Index.css" rel="stylesheet" type="text/css" /> 
} 

這是相當簡單的,對於許多簡單的適度複雜的網站可能是一個很好的解決方案。這對我來說還不夠,因爲我需要按照你的要求去做,而且只有在真正需要的時候才包含文件。此外,部分視圖和模板無法呈現部分,我發現它是一個巨大的PITA。所以我添加了一些HtmlHelper擴展方法。 (我只會顯示Javascript的代碼,因爲樣式表幾乎是相同的代碼,這些方法不允許重複的url。

Domain/HtmlHelperExtensions。CSHTML

public static class HtmlHelperExtensions 
{ 
    private const string _JSViewDataName = "RenderJavaScript"; 
    private const string _StyleViewDataName = "RenderStyle"; 

    public static void AddJavaScript(this HtmlHelper HtmlHelper, string ScriptURL) 
    { 
     List<string> scriptList = HtmlHelper.ViewContext.HttpContext.Items[HtmlHelperExtensions._JSViewDataName] as List<string>; 
     if (scriptList != null) 
     { 
      if (!scriptList.Contains(ScriptURL)) 
      { 
       scriptList.Add(ScriptURL); 
      } 
     } 
     else 
     { 
      scriptList = new List<string>(); 
      scriptList.Add(ScriptURL); 
      HtmlHelper.ViewContext.HttpContext.Items.Add(HtmlHelperExtensions._JSViewDataName, scriptList); 
     } 
    } 

    public static MvcHtmlString RenderJavaScripts(this HtmlHelper HtmlHelper) 
    { 
     StringBuilder result = new StringBuilder(); 

     List<string> scriptList = HtmlHelper.ViewContext.HttpContext.Items[HtmlHelperExtensions._JSViewDataName] as List<string>; 
     if (scriptList != null) 
     { 
      foreach (string script in scriptList) 
      { 
       result.AppendLine(string.Format("<script type=\"text/javascript\" src=\"{0}\"></script>", script)); 
      } 
     } 

     return MvcHtmlString.Create(result.ToString()); 
    } 
} 

更新查看/共享/ Layout.cshtml

<!doctype html> 
    <head> 
    <link href="/Styles/Global.css" rel="stylesheet" type="text/css" /> 
    @Html.RenderStyleSheets() 
    <script src="/Scripts/Global.js" type="text/javascript"></script> 
    @Html.RenderJavascripts() 

更新查看/主頁/ Index.cshtml

@Html.AddStyleSheet("/Styles/Home/Index.css") 

到您的下一個問題......

如何將這些東西封裝到MVC應用程序中的一個可重用實體中?也許是部分觀點?

Razor支持部分視圖和模板。雖然從技術上講,每種方法都有很大的重疊,但每種方法的設計都有一定的侷限性,以便程序員在需要時利用每種方法。

部分視圖做不是需要模型/類才能被渲染。這裏是一個完全有效的局部視圖:

/Views/Home/Index.cshtml

@Html.Partial("Partial-Menu") 

/Views/Shared/Partial-Menu.cshtml

<div id="menu"> 
    <a href="/">Home</a> 
    <a href="/Home/About">About Us</a> 
</div> 

模板上另一個,需要一個模型才能被渲染。這是因爲模板是一種將任何類或結構渲染爲編輯模板或顯示模板的方法。

/Models/Person.cs

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

/Controllers/HomeController.cs

public ActionResult Index() 
{ 
    Person model = new Person(); 
    model.FirstName = "Jon"; 
    model.LastName = "Doe"; 

    return this.View(model); 
} 

/Views/Home/Index.cshtml

@model Project1.Models.Person 

@Html.DisplayModel() 

@Html.EditforModel() 

/Views/Shared/DisplayTemplates/Person.cshtml

@model Project1.Models.Person 

<div>@Html.LabelFor(x => x.FirstName) @Html.DisplayFor(x => x.FirstName)</div> 
<div>@Html.LabelFor(x => x.LastName) @Html.DisplayFor(x => x.LastName)</div> 

/Views/Shared/EditorTemplates/Person.cshtml

@model Project1.Models.Person 

<div>@Html.LabelFor(x => x.FirstName) @Html.EditorFor(x => x.FirstName)</div> 
<div>@Html.LabelFor(x => x.LastName) @Html.EditrorFor(x => x.LastName)</div> 

我看到它的方式,有可能將任何模型進入數據輸入表格應該可能是一個模板。這是我喜歡封裝我的模型的方式。使用前面提供的擴展方法,我的部分視圖和模板都可以根據需要加載包含(目前,我的模型實際上只需要使用它們中的一個)。

我的首選項是每個頁面最多包含三個包含(每個Javascript和樣式)。我基本上有一個Global.css/js,一個控制器Home.css/js和一個index.css/js頁面作爲可能包含的內容。包含控制器的情況很少見。

0

他們必須從周圍用空行文字分隔。 最外面的塊元素的開始和結束標記不得縮進。 Markdown不能在HTML塊中使用。