MVC 3 Динамическая форма с использованием ViewModel - PullRequest
5 голосов
/ 16 февраля 2012

Я несколько недель пытался следовать парам уроков о том, как создать динамическую форму, дающую возможность добавить еще один «ингредиент» в форму.Вот статья, которой я пытался следовать.http://www.joe -stevens.com / 2011/07/24 / asp-net-mvc-2-проверка на стороне клиента для динамических полей, добавляемых с помощью ajax /

Прямо сейчас я просто работаю над добавлением нескольких recipeIngredients с помощью ссылки добавления, но мне нужно, чтобы при нажатии на ссылку было добавлено и «componentName», и «recipeIngredient» Amount.Моя проблема в том, что когда я запускаю приложение, форма для рецепта ингредиента имеет 0 вместо фактического текстового поля.Когда я нажимаю добавить новый ингредиент, я могу получить текстовое поле для добавления, но когда я набираю сумму и нажимаю сохранить, данные модели не передаются в контроллер ..

Я просто даже не знаюс чего начать с исправления этого, я не уверен, должен ли я использовать view-модель или я делаю это совершенно неправильно.Вот моя диаграмма базы данных 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>

Мой редактор с табличным представлением для рецептурного ингредиента:

@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>

        }
    }

МОЙ метод управления контроллером:

[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());
    }

Модель My View:

    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 ингредиента, и на мой взгляд был закомментированный код для их создания.Все, что я действительно хочу сделать - это заставить view-модель передавать данные формы в контроллер, и я могу обрабатывать данные, как это делает мой метод контроллера 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; }
}

1 Ответ

13 голосов
/ 16 февраля 2012

Есть много проблем с вашим кодом.Я предпочитаю идти шаг за шагом, чтобы проиллюстрировать упрощенный пример, который вы можете адаптировать к вашим потребностям.

Модели:

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>
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...