我几周来一直在尝试关注如何创建动态表单的几个教程,以便能够在表单中添加另一个“成分”。这是我试图遵循的文章。 http://www.joe-stevens.com/2011/07/24/asp-net-mvc-2-client-side-validation-for-dynamic-fields-added-with-ajax/
现在我正在使用添加链接添加多个recipeIngredients,但是我需要在单击链接时同时添加“ingredientName”和“recipeIngredient”数量。 我的问题是,当我运行应用程序时,recipeingredient的表单有一个0而不是一个实际的文本框。当我点击添加新成分时,我可以添加一个文本框,但是当我输入金额并单击保存时,模型数据不会传递给控制器..
我甚至不知道从哪里开始修复此问题,我不确定我是否应该使用视图模型或者我是否完全错误。这是我的数据库图表http://i44.tinypic.com/xp1tog.jpg。
这是我的CreateView:
@model ViewModels.RecipeViewModel
@using Helpers;
<h2>CreateFullRecipe</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$().ready(function () {
$("#add-recipeingredient").click(function () {
$.ajax({
url: '@Url.Action("GetNewRecipeIngredient")',
success: function (data) {
$(".new-recipeingredients").append(data);
Sys.Mvc.FormContext._Application_Load();
}
});
});
});
</script>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Recipe</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Recipe.RecipeName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Recipe.RecipeName)
@Html.ValidationMessageFor(model => model.Recipe.RecipeName)
</div>
</fieldset>
<fieldset>
<legend>RecipeIngredients</legend>
<div class="new-recipeingredients">
@Html.EditorFor(model => model.RecipeIngredients)
</div>
<div style="padding: 10px 0px 10px 0px">
<a id="add-recipeingredient" href="javascript:void(0);">Add another</a>
</div>
</fieldset>
<div>
<input type="submit" value="CreateFullRecipe" />
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
我对recipeingredient的editortemplateview:
@model Models.RecipeIngredient
@using Helpers;
@using (Html.BeginAjaxContentValidation("form0"))
{
using (Html.BeginCollectionItem("RecipeIngedients"))
{
<div style="padding: 5px 0px 5px 0px">
@Html.LabelFor(model => model.Amount)
@Html.EditorFor(model => model.Amount)
@Html.ValidationMessageFor(model => Model.Amount)
</div>
}
}
MY Controller相关方法:
[HttpGet]
public ActionResult CreateFullRecipe()
{
var recipeViewModel = new RecipeViewModel();
return View(recipeViewModel);
}
//
// POST: /Recipe/Create
[HttpPost]
public ActionResult CreateFullRecipe(RecipeViewModel recipeViewModel)
{
if (ModelState.IsValid)
{
db.Recipes.Add(recipeViewModel.Recipe);
db.SaveChanges();
int recipeID = recipeViewModel.Recipe.RecipeID;
for (int n = 0; n < recipeViewModel.RecipeIngredients.Count(); n++)
{
db.Ingredients.Add(recipeViewModel.Ingredients[n]);
int ingredientID = recipeViewModel.Ingredients[n].IngredientID;
recipeViewModel.RecipeIngredients[n].RecipeID = recipeID;
recipeViewModel.RecipeIngredients[n].IngredientID = ingredientID;
db.RecipeIngredients.Add(recipeViewModel.RecipeIngredients[n]);
db.SaveChanges();
}
return RedirectToAction("Index");
}
return View(recipeViewModel);
}
public ActionResult GetNewIngredient()
{
return PartialView("~/Views/Shared/IngredientEditorRow.cshtml", new Ingredient());
}
public ActionResult GetNewRecipeIngredient()
{
return PartialView("~/Views/Shared/_RecipeIngredientEditRow.cshtml", new RecipeIngredient());
}
我的视图模型:
public class RecipeViewModel
{
public RecipeViewModel()
{
RecipeIngredients = new List<RecipeIngredient>() { new RecipeIngredient() };
Ingredients = new List<Ingredient>() { new Ingredient() };
Recipe = new Recipe();
}
public Recipe Recipe { get; set; }
public IList<Ingredient> Ingredients { get; set; }
public IList<RecipeIngredient> RecipeIngredients { get; set; }
}
}
如果有任何其他信息需要帮助解决我的问题,请告诉我。这真让我疯狂,所以我期待着能得到任何帮助 谢谢!
我还想提一下,控制器发布方法createfullrecipe用于预先定义的列表,当我不担心给用户添加另一种成分的能力时它起作用,而我只是默认表单有2种成分和我的观点有这个注释掉的代码来创建它们。我真正想做的就是让viewmodel将表单数据传递给控制器,我可以像我的createfullrecipe控制器方法那样处理数据。
@* @for (int n = 0; n < Model.Ingredients.Count(); n++)
{
<div class="editor-label">
@Html.LabelFor(model => model.Ingredients[n].IngredientName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Ingredients[n].IngredientName)
@Html.ValidationMessageFor(model => model.Ingredients[n].IngredientName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.RecipeIngredients[n].Amount)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.RecipeIngredients[n].Amount)
@Html.ValidationMessageFor(model => model.RecipeIngredients[n].Amount)
</div>
}*@
以下是我的模型类:
public class Recipe
{
public int RecipeID { get; set; }
public string RecipeName { get; set; }
public string Description { get; set; }
public int? PrepTime { get; set; }
public int? CookTime { get; set; }
public string ImageURL { get; set; }
public virtual IList<RecipeTag> RecipeTags { get; set; }
public virtual IList<Rating> Ratings { get; set; }
public virtual IList<RecipeStep> RecipeSteps { get; set; }
public virtual IList<RecipeIngredient> RecipeIngredients { get; set; }
}
public class RecipeIngredient
{
public int RecipeIngredientID { get; set; }
public string IngredientDesc { get; set; }
public string Amount { get; set; }
public int RecipeID { get; set; }
public int? IngredientID { get; set; }
public virtual Recipe Recipe { get; set; }
public virtual Ingredient Ingredient { get; set; }
}
public class Ingredient
{
public int IngredientID { get; set; }
public string IngredientName { get; set; }
public virtual ICollection<RecipeIngredient> RecipeIngredients { get; set; }
}
答案 0 :(得分:13)
您的代码存在很多问题。我更喜欢一步一步地说明一个可以适应您需求的简化示例。
型号:
public class RecipeViewModel
{
public Recipe Recipe { get; set; }
public IList<RecipeIngredient> RecipeIngredients { get; set; }
}
public class Recipe
{
public string RecipeName { get; set; }
}
public class RecipeIngredient
{
public int Amount { get; set; }
[Required]
public string IngredientDesc { get; set; }
}
控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
var recipeViewModel = new RecipeViewModel();
return View(recipeViewModel);
}
[HttpPost]
public ActionResult Index(RecipeViewModel recipeViewModel)
{
if (!ModelState.IsValid)
{
// there wre validation errors => redisplay the view
return View(recipeViewModel);
}
// TODO: the model is valid => you could pass it to your
// service layer for processing
return RedirectToAction("Index");
}
public ActionResult GetNewRecipeIngredient()
{
return PartialView("~/Views/Shared/EditorTemplates/RecipeIngredient.cshtml", new RecipeIngredient());
}
}
查看(~/Views/Home/Index.cshtml
):
@model RecipeViewModel
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
$('#add-recipeingredient').click(function () {
$.ajax({
url: '@Url.Action("GetNewRecipeIngredient")',
type: 'POST',
success: function (data) {
$('.new-recipeingredients').append(data);
}
});
return false;
});
});
</script>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<div>
@Html.LabelFor(model => model.Recipe.RecipeName)
@Html.EditorFor(model => model.Recipe.RecipeName)
@Html.ValidationMessageFor(model => model.Recipe.RecipeName)
</div>
<fieldset>
<legend>RecipeIngredients</legend>
<div class="new-recipeingredients">
@Html.EditorFor(model => model.RecipeIngredients)
</div>
<div style="padding: 10px 0px 10px 0px">
<a id="add-recipeingredient" href="javascript:void(0);">Add another</a>
</div>
</fieldset>
<div>
<input type="submit" value="CreateFullRecipe" />
</div>
}
编辑模板(~/Views/Shared/EditorTemplates/RecipeIngredient.cshtml
):
@model RecipeIngredient
@using (Html.BeginCollectionItem("RecipeIngredients"))
{
<div>
@Html.LabelFor(model => model.Amount)
@Html.EditorFor(model => model.Amount)
@Html.ValidationMessageFor(model => model.Amount)
</div>
<div>
@Html.LabelFor(model => model.IngredientDesc)
@Html.EditorFor(model => model.IngredientDesc)
@Html.ValidationMessageFor(model => model.IngredientDesc)
</div>
}