Проверка ModelState OnPost только свойств видимой формы на страницах бритвы - PullRequest
0 голосов
/ 11 декабря 2018

Я создал страницу бритвы, которая имеет следующие свойства:

[BindProperty]
public CustomerViewModel Customer { get; set; }

[BindProperty]
public CustomerContactViewModel Contact { get; set; }

Внутри CustomerViewModel и CustomerContactViewModel У меня есть несколько аннотаций данных, которые делают поля обязательными для заполнения.

Эта страница имеет 3 просмотравстроенный в одну.

Две вкладки: [Информация о клиенте] [Контакты]

Вкладка [Информация о клиенте] имеет форму для редактирования клиента и использует CustomerViewModel

[Контакты] на вкладке изначально есть список сетки, но если щелкнуть по строке редактирования, пользователь переместится на ту же страницу, но с параметром запроса, заставляющим форму появиться вместо сетки.

Вот моя проблема:

У меня есть две отдельные кнопки отправки на странице, которые используют свойство asp-page-handler для направления на правильный PostAction либо SaveCustomer, либо SaveContact.

При проверке, допустим ли ModelState вв верхней части каждого действия, даже если форма, отображаемая на странице, действительна, другая форма, использующая другую модель, недействительна.

Любаяидеи о том, как я могу это исправить или как я могу переделать несколько вещей, чтобы это не было проблемой?

Вот мой код представления:

@page
@model Messenger.Web.Pages.Customers.EditModel
@{
    ViewData["Title"] = "Edit";
}

<ul class="nav nav-tabs" id="myTab" role="tablist">
    <li class="nav-item">
        <a class="nav-link@(Model.ViewType == EditModel.ViewTypes.EditCustomer ? " active" : "")" id="info-tab" data-toggle="tab" href="#info" role="tab" aria-controls="info" aria-selected="true">Info</a>
    </li>
    <li class="nav-item">
        <a class="nav-link@(Model.ViewType == EditModel.ViewTypes.EditContact ? " active" : "")" id="contacts-tab" data-toggle="tab" href="#contacts" role="tab" aria-controls="contacts" aria-selected="false">Contacts</a>
    </li>
</ul>
<div class="tab-content" id="myTabContent">
    <div class="tab-pane fade @(Model.ViewType == EditModel.ViewTypes.EditCustomer ? " show active" : "")" id="info" role="tabpanel" aria-labelledby="info-tab">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>

            <a asp-page="Index" class="btn btn-outline-secondary">Cancel</a>
            <button asp-page-handler="SaveCustomer" type="submit" class="btn btn-outline-success ml-1">Save</button>
        </form>
    </div>
    <div class="tab-pane fade @(Model.ViewType == EditModel.ViewTypes.EditContact ? " show active" : "")" id="contacts" role="tabpanel" aria-labelledby="contacts-tab">
        @if (Model.ViewType == EditModel.ViewTypes.EditCustomer)
        {
            <table class="table">

            </table>
        }
        else
        {
            <form method="post">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>

                <a asp-page="./Index" asp-route-CustomerId="@Model.Customer.Id" class="btn btn-outline-secondary">Cancel</a>
                <button asp-page-handler="SaveContact" type="submit" class="btn btn-outline-success ml-1">Save</button>
            </form>
        }
    </div>
</div>

Вот код позади:

public enum ViewTypes
{
    EditCustomer = 0,
    EditContact = 1
}

public ViewTypes ViewType { get; set; } = ViewTypes.EditCustomer;

[BindProperty]
public CustomerViewModel Customer { get; set; }

[BindProperty]
public CustomerContactViewModel Contact { get; set; }

public async Task<IActionResult> OnGetAsync(int? customerId, string contactId)
{
    if (customerId == null && contactId == null)
    {
        return NotFound();
    }

    if (customerId != null)
    {
        var customerFromDb = await _customerRepository.GetByIdWithContactsAsync(customerId.Value);

        if (customerFromDb == null)
        {
            return NotFound();
        }

        Customer = _mapper.Map<Customer, CustomerViewModel>(customerFromDb);

        if (!string.IsNullOrEmpty(contactId))
        {
            ViewType = ViewTypes.EditContact;
            var contactFromDb = customerFromDb.Contacts.SingleOrDefault(x => x.Id == contactId);

            if (contactFromDb == null)
            {
                return NotFound();
            }

            Contact = _mapper.Map<HomeUser, CustomerContactViewModel>(contactFromDb);
        }
    }

    return Page();
}

        public async Task<IActionResult> OnPostSaveCustomerAsync()
{
    if (!ModelState.IsValid)
    {
        CreateDropdownData();
        return Page();
    }

    var customerFromDb = await _customerRepository.GetByIdAsync(Customer.Id);

    if (customerFromDb == null)
    {
        return NotFound();
    }

    customerFromDb.FirstName = Customer.FirstName;
    customerFromDb.MiddleName = Customer.MiddleName;
    customerFromDb.LastName = Customer.LastName;
    customerFromDb.Birthdate = Customer.Birthdate;
    customerFromDb.ActiveIep = Customer.ActiveIep;
    customerFromDb.Active = Customer.Active;
    customerFromDb.EslLep = Customer.EslLep;
    customerFromDb.Grade = Customer.Grade;
    customerFromDb.Homeroom = Customer.Homeroom;
    customerFromDb.Gender = Customer.Gender;

    try
    {
        await _customerRepository.UpdateAsync(customerFromDb);
    }
    catch (DbUpdateConcurrencyException)
    {
        throw;
    }

    return RedirectToPage("./", new { CustomerId = Customer.Id });
}

public async Task<IActionResult> OnPostSaveContactAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    var customerContactFromDb = await _homeUserRepository.GetByIdAsync(Contact.Id);

    // Map View Model to Home User (Customer Contact)
    customerContactFromDb.FirstName = Contact.FirstName;
    customerContactFromDb.LastName = Contact.LastName;
    customerContactFromDb.UserName = Contact.Email;
    customerContactFromDb.Email = Contact.Email;
    customerContactFromDb.PhoneNumber = Contact.PhoneNumber;
    customerContactFromDb.EmailNotifications = Contact.EmailNotifications;
    customerContactFromDb.TextNotifications = Contact.TextNotifications;

    await _userManager.UpdateAsync(customerContactFromDb);
    if (!string.IsNullOrEmpty(Contact.Password))
    {
        var resetToken = await _userManager.GeneratePasswordResetTokenAsync(customerContactFromDb);
        await _userManager.ResetPasswordAsync(customerContactFromDb, resetToken, Contact.Password);
    }

    return RedirectToPage("./", new { CustomerId = customerContactFromDb.CustomerId });
}
...