यह blog post में चरण-दर-चरण मार्गदर्शिका शामिल है जो यह बताती है कि इसे कैसे प्राप्त किया जाए।
अद्यतन:
टिप्पणी अनुभाग मैं कदम कैसे अपने परिदृश्य के लिए ऊपर उल्लिखित लेख अनुकूल करने के लिए कदम को दर्शाता हुआ हूँ में अनुरोध के रूप में।
मॉडल:
public class MyOtherModelObject
{
public string Name { get; set; }
public string Description { get; set; }
}
public class MyModelObject
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<MyOtherModelObject> OtherModelObjects { get; set; }
}
नियंत्रक:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyModelObject
{
Id = 1,
Name = "the model",
Description = "some desc",
OtherModelObjects = new[]
{
new MyOtherModelObject { Name = "foo", Description = "foo desc" },
new MyOtherModelObject { Name = "bar", Description = "bar desc" },
}.ToList()
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyModelObject model)
{
return Content("Thank you for submitting the form");
}
public ActionResult BlankEditorRow()
{
return PartialView("EditorRow", new MyOtherModelObject());
}
}
देखें (~/Views/Home/Index.cshtml
):
@model MyModelObject
@using(Html.BeginForm())
{
@Html.HiddenFor(x => x.Id)
<div>
@Html.LabelFor(x => x.Name)
@Html.EditorFor(x => x.Name)
</div>
<div>
@Html.LabelFor(x => x.Description)
@Html.TextBoxFor(x => x.Description)
</div>
<hr/>
<div id="editorRows">
@foreach (var item in Model.OtherModelObjects)
{
@Html.Partial("EditorRow", item);
}
</div>
@Html.ActionLink("Add another...", "BlankEditorRow", null, new { id = "addItem" })
<input type="submit" value="Finished" />
}
आंशिक (~/Views/Home/EditorRow.cshtml
):
@model MyOtherModelObject
<div class="editorRow">
@using (Html.BeginCollectionItem("OtherModelObjects"))
{
<div>
@Html.LabelFor(x => x.Name)
@Html.EditorFor(x => x.Name)
</div>
<div>
@Html.LabelFor(x => x.Description)
@Html.EditorFor(x => x.Description)
</div>
<a href="#" class="deleteRow">delete</a>
}
</div>
स्क्रिप्ट:
$('#addItem').click(function() {
$.ajax({
url: this.href,
cache: false,
success: function (html) {
$('#editorRows').append(html);
}
});
return false;
});
$('a.deleteRow').live('click', function() {
$(this).parents('div.editorRow:first').remove();
return false;
});
टिप्पणी: BeginCollectionItem
कस्टम सहायक एक ही लेख मैं करने के लिए लिंक करने के बाद से लिया जाता है, लेकिन मैं इसे यहाँ जवाब की पूर्णता के लिए उपलब्ध कराने के कर रहा हूँ:
public static class HtmlPrefixScopeExtensions
{
private const string idsToReuseKey = "__htmlPrefixScopeExtensions_IdsToReuse_";
public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName)
{
var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName);
string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : Guid.NewGuid().ToString();
// autocomplete="off" is needed to work around a very annoying Chrome behaviour whereby it reuses old values after the user clicks "Back", which causes the xyz.index and xyz[...] values to get out of sync.
html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, html.Encode(itemIndex)));
return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex));
}
public static IDisposable BeginHtmlFieldPrefixScope(this HtmlHelper html, string htmlFieldPrefix)
{
return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
}
private static Queue<string> GetIdsToReuse(HttpContextBase httpContext, string collectionName)
{
// We need to use the same sequence of IDs following a server-side validation failure,
// otherwise the framework won't render the validation error messages next to each item.
string key = idsToReuseKey + collectionName;
var queue = (Queue<string>)httpContext.Items[key];
if (queue == null)
{
httpContext.Items[key] = queue = new Queue<string>();
var previouslyUsedIds = httpContext.Request[collectionName + ".index"];
if (!string.IsNullOrEmpty(previouslyUsedIds))
foreach (string previouslyUsedId in previouslyUsedIds.Split(','))
queue.Enqueue(previouslyUsedId);
}
return queue;
}
private class HtmlFieldPrefixScope : IDisposable
{
private readonly TemplateInfo templateInfo;
private readonly string previousHtmlFieldPrefix;
public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix)
{
this.templateInfo = templateInfo;
previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
}
public void Dispose()
{
templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix;
}
}
}
आप http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx पर एक नज़र, हालांकि यह है कि क्या उस्तरा वाक्य रचना है हो सकता है (और न ही MVC4 यह संभवतः दे सकता है एक विचार) –
पहली नज़र में। ऐसा लगता है कि यह एक सूची के लिए काम करेगा, लेकिन यह एक सूची के लिए काम करेगा जो किसी अन्य वस्तु का हिस्सा है, और क्या यह मॉडल को बांधने में सक्षम होगा? – DaveH