ASP.NET MVC 3 - ViewModel & Refresh - Проблемы - PullRequest
2 голосов
/ 09 марта 2011

Я попал в сценарий привязки ViewModel и обновления.

Сценарий: Как администратор я хочу создать учетную запись пользователя и на основе выбранной роли из DropDownList обновить ФОРМУ, чтобы выбрать с помощью флажков определенные доступы (bool), связанные с ролью.

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

Моя ViewModel:

public class CreateViewModel
{
    public User User { get; set; }
    public IEnumerable<Role> Roles { get; set; }
    public IEnumerable<RoleAccess> RoleAcceses { get; set; }
    public Role SelectedRole { get; set; }


    public void Refresh()
    {
        User.UserAccesses.Clear();
        foreach (var item in RoleAcceses.Where(x => x.RoleId == SelectedRole.Id))
        {
            User.UserAccesses.Add(new UserAccess { UserId = User.Id, Access = item.Access, AccessId = item.AccessId, Value = item.Value });
        }
    }
}

Как видно из приведенного выше кода, у меня есть коллекция RoleAccess со значениями по умолчанию для конкретной роли. Метод Refresh очищает фактическую коллекцию UserAccess и повторно заполняет ее для SelectedRole.

Мои вопросы:

  1. Возможно ли сделать это без jQuery? Каково ваше мнение?
  2. Если возможно обновить FORM без jQuery, как опубликовать его без потери значений, введенных администратором? Здесь я не могу добавить другой @BeginForm, потому что я потеряю фактический контекст данных, верно?
  3. Если jQuery - единственное решение, как написать действие контроллера, которое проверяет фильтрацию jQuery?
  4. Как должна выглядеть функция jQuery для замены флажков Binded to ViewModel?

Мой Куррент-контроллер Действие:

public class AccountController : Controller
{
    IAccountService accountService;

    public AccountController()
    {
        accountService = new AccountService();
    }

    [HttpGet]
    public ActionResult Create(int role = 1)
    {
        IEnumerable<RoleAccess> roleAccesses = null;
        IEnumerable<Role> roles = null;

        roleAccesses = accountService.GetRoleAcgesses();
        roles = accountService.GetRoles();

        var createViewModel = new CreateViewModel();
        createViewModel.RoleAcceses = accountService.GetRoleAccesses();
        createViewModel.Roles = accountService.GetRoles();
        createViewModel.SelectedRole = createViewModel.Roles.FirstOrDefault(x => x.Id == role);
        createViewModel.Refresh();

        return View(createViewModel);
    }

    public ActionResult Refresh(int role)
    {
        return RedirectToAction("Create", "Account", new { role });
    }

    [HttpPost]
    public ActionResult Create([Bind(Prefix = "User")] Models.User user, FormCollection formsCollection)
    {
        var viewModel = new CreateViewModel();
        UpdateModel<CreateViewModel>(viewModel, new[] { "User.Login", "User.Password", "User.FirstName", "User.LastName" });

        viewModel.User.RoleId = Convert.ToInt32(formsCollection["Role"]);

        if (ModelState.IsValid)
        {
            bool result = accountService.CreateAccount(viewModel.User);

            if (!result)
            {
                // SEND INFO ABOUT FAILURE
            }
            else
            {
                return RedirectToAction("list");
            }
        }

        return View();
    }

    [HttpGet]
    public ActionResult List()
    {
        var accounts = accountService.GetAccounts();
        var viewModel = new ListViewModel() { Accounts = accounts };
        return View(viewModel);
    }
}

My View:

@model VDOT.Web.AccountViewModels.CreateViewModel
@{
    ViewBag.Title = "Create";
}
<h2>Create</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>

@using (Html.BeginForm("create", "account"))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
    <legend>CreateViewModel</legend>
    <fieldset>
        <div class="editor-label">
            @Html.LabelFor(model => model.User.Login)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.User.Login)
            @Html.ValidationMessageFor(model => model.User.Login)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.User.Password)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.User.Password)
            @Html.ValidationMessageFor(model => model.User.Password)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.User.FirstName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.User.FirstName)
            @Html.ValidationMessageFor(model => model.User.FirstName)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.User.LastName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.User.LastName)
            @Html.ValidationMessageFor(model => model.User.LastName)
        </div>
        <div class="editor-field">
            <select id="paging" onchange="location.href=this.value">
                @foreach (var item in Model.Roles)
                {
                    <option value="@Url.Action("create", "account", new { role = item.Id })">
                        @item.Name
                    </option>
                }
            </select>
        </div>
        <div class="editor-field">
            @foreach (var item in Model.User.UserAccesses)
            {
                @Html.CheckBox(item.Access.Name, item.Value);
                <br />
            }
        </div>
    </fieldset>
</fieldset>
<fieldset>
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>
}

Спасибо за любую помощь!

1 Ответ

1 голос
/ 06 апреля 2011

Я думаю, что вы ищете способ связать свою коллекцию пользовательских доступов с вашей моделью пользовательского представления.Благодаря этому ваша полная модель будет устойчивой при обратной отправке, что позволит вам достичь любой необходимой функциональности без сценариев (хотя вы можете затем использовать jQuery, если он доступен, для улучшения страницы для «более плавной» функциональности).

Отличный способ создания привязок свойств списка моделей доступен в блоге Стивена Сандерсона, здесь .

...