2013-03-12 105 views
0

我有這個模型有另一個模型的列表。然後在我看來,我的表格爲我的主模型填充了幾個字段。但我希望這種形式也能夠添加其他類型的X模型,並且都是有線的,我想知道如何正確地做到這一點。具有模型列表的模型的MVC客戶端驗證

因此,這裏有我的兩個型號:

public class MyMainModel 
{ 

    public int MyMainId { get; set; } 

    [Required(ErrorMessage = "Groovy name required")] 
    [Display(Name = "MyMainModel's groovy name:")] 
    public string Name { get; set; } 

    public List<MySubModel> MySubModels { get; set; } 

} 

public class MySubModel 
{ 

    public int MySubId { get; set; } 

    [Required(ErrorMessage = "Cool name required")] 
    [Display(Name = "MySubModel's cool name:")] 
    public string Name { get; set; } 

} 

當我打我的控制器,我的「創造」的看法,我通過這個動作:

public ActionResult SomePageAboutCreating() 
{ 
    // [...] Some other stuff 
    return View(new MyMainModel()); 
} 

現在這個發送到我的強類型查看:

@model myFunProject.WebModels.MyMainModel 

<div> 
    <form id="my-create-form" onsubmit="CreateMyMainModel(this); return false;"> 
     @Html.AntiForgeryToken() 
     @Html.ValidationSummary() 

     <div class="result" style="background-color: silver;">This is the operation result box</div> 
     <img class="loading" src="/Images/ajax-loader.gif" alt="Loading..." width="16" height="16" style="display: none;" /> 

     <section> 
      @Html.LabelFor(m => m.Name) 
      @Html.TextBoxFor(m => m.Name) 
      @Html.ValidationMessageFor(m => m.Name) 
     </section> 

     <!-- Here begins the fields for my list of "MySubModel" --> 
     @Html.EditorFor(x => x.MySubModels) 

     <!-- Here I'm thinking about a javascript that will add the previous fields X times so that the user can create "MyMainModel" as well as x times "MySubModel"... --> 

     <input type="submit" class="btn-send" id="my-create-form-submit" value="Send" /> 
    </form> 
</div> 

所以我想我必須在這裏使用EditorTemplates ...所以我安裝在我的/ Views/EditorTemplates/MySub Models.cshtml(命名反對我「MyMainModel」的屬性),然後當我寫我的形式在那裏,我很困惑...

@model myFunProject.WebModels.MyMainModel 

@*<section> 
    @Html.LabelFor(m => m.Name) 
    @Html.TextBoxFor(m => m.Name) 
    @Html.ValidationMessageFor(m => m.Name) 
</section>*@ 

所以在這裏我不知道要放什麼東西在這裏...我希望我的名稱屬性是「MySubModel」之一。當用戶看到這個表單時,比如說他會經歷這種情況:

  1. 輸入「MyMainModel」的名稱。
  2. 轉到其他人的名字框和在「MySubModel的第一個實例的名稱罷了。
  3. 然後,他會點擊一個特殊的按鈕,將操作DOM追加另一MySubModel.Name場。
  4. 他會寫在第二個「MySubModel」的名字。
  5. 他會點擊提交。

AJAX調用我擺在那裏我確定做配線,但我的困惑帶有我編寫的代碼編輯器模板,然後我有點想知道我將如何創建一個新的領域(第二個「MySubModel」例如...)。

任何幫助將不勝感激,我已經通過了許多關於這個主題的文章,但還沒有發現這種情況。謝謝!

編輯:

我會添加動作(過於簡化的版本,嘿嘿)由我的阿賈克斯提交表單時調用。

public ActionResult CreateMyMainModel(MyMainModel myMainModel) { 

    // [...] Do stuff like save to database... 
    // var aGroovyNAme = myMainModel.Name; 

    foreach(var mySubModel in myMainModel.MySubModels) { 
     // Here I would have the sub models available to manipulate... 
     // var aCoolName = mySubModel.Name; 
    } 
    return Content("ok"); 

} 
+0

的[ASP.Net MVC4綁定「創建視圖」到包含列表中選擇模型]可能的複製(http://stackoverflow.com/questions/12974957/asp-net-mvc4-bind-a-create-view-to-a-model-that-c​​ontains-list) – halfer 2016-02-14 21:36:49

+0

我已經添加了一個dup建議基於來自@Savantes的回答。 – halfer 2016-02-14 21:37:09

回答

1

我已經通過有關科目接近這個文章很多了,但沒有發現這種情況呢。

我真的建議你閱讀從史蒂芬·桑德森的editing a variable length list文章這說明了一個非常不錯的方法來處理這種情況。他提供了一個自定義的幫助程序,可以用來爲輸入字段名稱生成非順序索引(guid),從而允許動態地輕鬆移除元素,而不會在索引中留下。當用戶決定添加另一個項目時,將對控制器操作進行AJAX調用,該操作只返回空模板(部分)。

你也可以純粹在客戶端使用javascript來完成此操作。 Steven Sanderson在this similar article中使用knockoutjs說明了這種方法。

這兩篇文章實際上是動態編輯ASP.NET MVC中的變量長度列表項的最佳方法。閱讀它們將有助於更好地理解ASP.NET MVC中模型綁定中的一些核心概念。

+0

嗨達林,感謝您的有用的鏈接,我更新了我的問題的更多細節,我可以看到與史蒂文的例子的區別是,我想收到一個模型時提交表單,而不是一個列表。 (我認爲至少有所不同......) – 2013-03-12 23:24:15

+0

@不,沒有什麼不同。唯一改變的是,你不用'IEnumerable '工作,而是使用'MyMainModel',它具有'IEnumerable '類型的屬性。但是完全一樣的原則適用。 – 2013-03-13 06:40:15

0

我有一個項目類似的問題,我想驗證在某些情況下某些字段 ,而不是對他人(即在保存不驗證,但在提交驗證一切。

最後我做的一切手動javascript和回發一個JSON對象。

經過思考我寧願操縱JavaScript文件(MicrosoftMVCValidation.js)。

對於模型的結合問題,我建議在尋找客戶定製模型綁定驗證。

我發現使用EditorTemplates有點煩人,尤其是局部視圖。

我發現asp.net mvc 3在模型綁定方面有點弱。我希望一些問題能夠在mvc 4中得到解決,但從目前我所看到的情況來看,MVC4主要是用於創建Windows Phone應用程序的升級。

下面是模型中小數屬性的自定義模型聯編程序示例。

您可以對自己的自定義模型使用相同的邏輯。

我發現有些場合我想將大型網頁上的實體集合與模型綁定,而不是僅僅綁定基本的屬性集合。

public class DecimalModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

     //return valueProviderResult == null ? base.BindModel(controllerContext, bindingContext) : Convert.ToDecimal(valueProviderResult.AttemptedValue); 


     if (valueProviderResult == null) 
      return base.BindModel(controllerContext, bindingContext); 
     else if (valueProviderResult.AttemptedValue == "") 
      return base.BindModel(controllerContext, bindingContext); 
     else 
      return Convert.ToDecimal(valueProviderResult.AttemptedValue); 

    } 
}