Как вставить несколько строк из POST - PullRequest
0 голосов
/ 30 ноября 2019

У меня есть вид, который содержит n полей ввода (количество будет варьироваться в зависимости от разных критериев). значение каждого поля ввода должно быть вставлено в базу данных в отдельной строке. Моя проблема в том, что в базу данных вставляется только первое поле ввода. Контроллер выглядит так:

public ActionResult Create([Bind(Include = "Id,MemberId,Rated,Rating")] Rating rating)
        {
                if (ModelState.IsValid)
                {
                    db.Ratings.Add(rating);
                    db.SaveChanges();                  
                }

Значение MemberId одинаково для каждой строки, но Rated и Rating будут отличаться.

Моя модель выглядит так:

[Table("Rating")]
    public partial class Rating
    {
        public int Id { get; set; }

        public int? MemberId { get; set; }

        public int Rated { get; set; }

        [Column("Rating")]
        public int Rating { get; set; }

        public virtual TeamMember TeamMember { get; set; }
    }

Вид выглядит следующим образом:

@model Teamer.Models.Rating

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Rating</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="form-group">
            @{
                int count = 0;

                foreach (var item in ViewBag.MemberId)
                {
                    string rater = Request.Cookies["rater"]["name"].ToString();
                    string raterId = Request.Cookies["rater"]["raterId"];

                    if (item.Name.ToLower() != rater.ToLower())
                    {
                        if (ViewBag.raterId != null)
                        {
                            foreach (var raterid in ViewBag.raterId)
                            {
                                <input type="hidden" name="MemberId" value="@raterid" />
                            }
                        }
                        <div class="col-md-10">
                            <label class="control-label col-md-2" for="@item.Name">@item.Name</label>
                            <input type="number" name="Rating-@count" value="0" />
                            <input type="hidden" name="Rated" value="@item.Id" />
                        </div>  
                        count++;
                    }
                }
            }
        </div>

        <input type="hidden" name="count" value="@count" />

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

Я предполагаю, мне нужно перебирать значения по одному, но я не могу заставить это работать, так что, возможно, я 'На этом далеко не все.

РЕДАКТИРОВАТЬ

ОК, так что теперь я начал работать с простым, хотя, возможно, и некрасивым решением. Мой контроллер теперь выглядит так:

public ActionResult Create(Rating rating)
        {
            int count = int.Parse(Request.Form["count"]);

            for (int i = 0; i < count; i++)
            {
                string test = Request.Form["MemberId"];
                rating.MemberId = int.Parse(test);
                rating.Rated = int.Parse(Request.Form["Rated-" + i]);
                rating.Rating1 = int.Parse(Request.Form["Rating1-" + i]);
                db.Ratings.Add(rating);

                if (ModelState.IsValid)
                {
                    db.SaveChanges();
                }
            }

            return RedirectToAction("Index");

        }

И мой вид:

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Rating</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div class="form-group">
        @{
            int count = 0;
            string raterId = Request.Cookies["rater"]["raterId"];
            foreach (var item in ViewBag.MemberId)
            {
                string rater = Request.Cookies["rater"]["name"].ToString();


                if (item.Name.ToLower() != rater.ToLower())
                {

                    <div class="col-md-10">
                        <label class="control-label col-md-2" for="@item.Name">@item.Name</label>
                        <input type="number" name="Rating1-@count" value="0" />
                        <input type="hidden" name="Rated-@count" value="@item.Id" />
                    </div>

                    count++;
                }

            }
        }
    </div>

    <input type="hidden" name="MemberId" value="@raterId" />

    <input type="hidden" name="count" value="@count" />

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

Это достаточно просто, но я чувствую, что есть лучший, более чистый способ. Есть предложения?

Ответы [ 2 ]

0 голосов
/ 01 декабря 2019

Клиент отправляет массив в контроллер, требуется изменение привязки. Контроллер должен принять массив или коллекцию Rating:

   public ActionResult Create(Icollection<Rating> ratings)
   {
       if (ModelState.IsValid)
       {
        //saving...              
       }
    }

Обновление: как один из хороших методов, лучше работать с DTO, а не с объектом базы данных, вы можете создатьRatingDto Класс:

  public partial class RatingDto
  {
      public int MemberId { get; set; }

      public int Rate { get; set; }
  }

И не забывайте об изменении Просмотр:

<div class="col-md-10">
   <input type="hidden" name="MemberId" value="@raterId" />
   <input type="number" name="Rate" value="0" />
 </div>

Привязка в Asp.net MVC работает следующим образом, привяжите атрибут html name к propertyимя в коде C #. Довольно сложно понять, чего ожидает другой программист от своего кода, но Key указывает:

  • Вместо ViewBags и Cookies используйте Model
  • Обратите внимание на то, как работает Binding
  • Замените Entity на Dto
  • Используйте отладчик (Google Chrome, Firefox и т. Д.), Чтобы проверить, что вы отправляете в браузер

Надеюсь, это поможет.

0 голосов
/ 01 декабря 2019

Я вижу пару проблем, но в конце вы не публикуете то, что ожидает ваш контроллер. Ваш контроллер ожидает получить Rating (т.е. Id, MemberId, Rated и Rating), но вы на самом деле публикуете что-то вроде

MemberId=raterId (repeated by as many ViewBag.raterId you have)
Rating-0=0
Rated=memberX_Id
Rating-1=0
Rated=memberY_Id
Rating-2=0
Rated=memberZ_Id
(...)
Rating-n=0
Rated=memberM_Id
count=(n+1)

Если вы проверяете свои опубликованные данные, вы должны иметь толькоMemberId и Rated заполнены.

Чтобы достичь желаемого, вам потребуется список Rating или другая структура на стороне контроллера. Помните, что если вы хотите опубликовать массив, он должен выглядеть примерно так:

MemberId[0]=
Rated[0]=
Rating[0]=
MemberId[1]=
Rated[1]=
Rating[1]=
(...)
MemberId[n]=
Rated[n]=
Rating[n]=

Также обратите внимание, что MemberId и Rated переопределяются в ваших циклах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...