Как отправить ObjectViewModel из представления в контроллер в ASP.NET MVC C #?

1

Я работаю в веб-приложении ASP.NET, используя шаблон MVC.

Я пытаюсь отправить или передать ObjectViewModel из View.cshtml в контроллер, но в контроллере ObjectViewModel прибыл как null.

Идея заключается в следующем: я показываю представление IndexUsersInActiveDirectory.cshtml с коллекцией объекта типа RegisterViewModel. В этом представлении есть @Html.ActionLink для отправки элемента коллекции в контроллер регистра:

IndexUsersInActiveDirectory.csthml

@model IEnumerable<SecureEscuelaWithIdentity.Models.RegisterViewModel>
@{
    ViewBag.Title = "IndexUsersInActiveDirectory";
}

<h2>IndexUsersInActiveDirectory</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
    <th>
        @Html.DisplayNameFor(model => model.UserName)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.Email)
    </th>
    <th></th>
</tr>

@foreach (var item in Model) {
<tr>
    <td>
        @Html.DisplayFor(modelItem => item.UserName)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Email)
    </td>
    <td>
        @Html.ActionLink("Select", "Register", new { item })
    </td>
</tr>
}
</table>

Регистр контроллера следующий:

//
// GET: /Account/Register
[Authorize(Roles = "Admin")]
public ActionResult Register(RegisterViewModel model)
{
    return View(model);
}

Класс RegisterViewModel:

public class RegisterViewModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [Display(Name = "Email")]
    public string Email { get; set; }
}

View Register.cshtml

    @model SecureEscuelaWithIdentity.Models.RegisterViewModel
@{
    ViewBag.Title = "Register";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("RegisterInApp", "Account", FormMethod.Post, new { @class =    "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Create a new account.</h4>
    <hr />
    @Html.ValidationSummary()
    <li>@Html.ActionLink("ActiveDirectory", "IndexUsersInActiveDirectory", "Account")</li>
    <div class="form-group">
        @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
        </div>
    </div>

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

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Как отправить весь элемент коллекции (как модель) на контроллер?

Теги:
razor
controller

3 ответа

2

Есть 2 проблемы

1) У вас отсутствует нуль для 4-го параметра ActionLink

@Html.ActionLink("Select", "Register", new { item }, null)

Без этого 4-го параметра он принимает третий параметр - это атрибуты HTML, а не параметры запроса.

Я считаю, что этот маленький 4-й параметр "quirk" является одним из самых раздражающих переопределений в MVC.

2) Ваш item должен быть простым значением данных, которое может быть передано через строку запроса

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

@Html.ActionLink("Select", "Register", new { name = item.Name, email = item.Email }, null)

Ссылки на действия не делают обратной передачи, они просто создают привязывающие ссылки на странице, поэтому любые значения должны быть переданы в строке запроса.

Измените действие приема, чтобы оно соответствовало:

[Authorize(Roles = "Admin")]
public ActionResult Register(string name, string email)
{
    RegisterViewModel model = new RegisterViewModel()
    {
         Name = name, 
         Email = email
    };
    return View(model);
}

Но я оставляю эти детали до вас :)

1

Решение, предлагаемое TrueBlueAussie, подходит для сценариев, в которых нет проблемы с отображением строки запроса в адресной строке браузера.

Если это так, @Html.ActionLink может выглядеть так:

@Html.ActionLink("Select", "Register", new {item}, null) 

так как контроллер возьмет "элемент" как объект RegisterViewModel (хотя на самом деле это будет запрос). Примечание: не забывая 4-й параметр, который внес TrueBlueAussie "null".

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

[Authorize (Roles = "Admin")]
public ActionResult Register (RegisterViewModel model) 
{ 
    return View (model); 
} 

Оно работает!

Как упоминалось выше, это отображает запрос в представлении "Регистр", что неверно в моей реализации. Я не хочу показывать эту строку запроса в адресной строке.

Для этого я добавил промежуточного контроллера, ответственного за получение "элемента" (от IndexUsersInActiveDirectory.csthml) в качестве объекта RegisterViewModel (на самом деле это запрос) и добавить этот словарь в словарь TempData с помощью ключа, называемого "модель".

Вот контроллер RegisterTemp:

[Authorize (Roles = "Admin")] 
public ActionResult RegisterTemp (RegisterViewModel model) 
{ 
    TempData ["model"] = model; 
    return RedirectToAction ("Register"); 
} 

В представлении "IndexUsersInActiveDirectory.csthml" точка @ActionLink указывает на контроллер RegisterTemp, а не на регистр контроллера, который выглядит следующим образом:

@ Html.ActionLink ("Select", "RegisterTemp", new {item}, null) 

Важно, что RegisterTemp возвращает вид "RedirectToAction" в регистр.

И, наконец, когда контроллер RegisterTemp возвращает контроллер RedirectToAction для регистрации, он берет элемент с "модельным" ключом из словаря TempData, чтобы вернуть его в представление. Таким образом, контроллер регистра:

// 
// GET: / Account / Register 
[Authorize (Roles = "Admin")] 
public ActionResult Register () 
{ 
    return View (TempData ["model"]); 
} 

Я упомянул, что решение, предложенное @TrueBlueAussie, полностью функционально для сценария, что не важно, чтобы показать запрос.

Решение, которое я только что рассмотрел сейчас, заключается в том, чтобы не показывать эту последовательность.

Если есть более правильное решение для решения моего сценария, приветствуется.

0

Вы должны перебирать элементы с помощью цикла "for", например in (int i; я <= elements.Length -1; i++) элементы [i].etc;

Таким образом, сбор не теряется на почте.

Читайте это для более подробной информации: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

  • 0
    Нет. В этом вопросе нет входов редактирования внутри цикла foreach. Проблема в ActionLinks.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню