Состояние проверки .net core 2.1: неверно - PullRequest
0 голосов
/ 17 сентября 2018

Следующий простой код .NET Core 2.1 MVC сообщает о состоянии проверки: недействительно, когда я отправляю на создание. Все отлично работает без собственности владельца; и это работает, если свойство Owner не требуется.

Владелец - это текущий пользователь, который находится в контексте серверной части, и его не следует отправлять со стороны клиента, поэтому Create.cshtml не имеет ввода Owner в форме.

Ошибка:

info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method AnnouncementApp.Controllers.AnnouncementsController.Create (AnnouncementApp) with arguments (AnnouncementApp.Models.Announcement) - Validation state: Invalid

Модель:

using System;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using AnnouncementApp.Models.Attributes;
using Microsoft.AspNetCore.Identity;
//using System.Security.Claims;

namespace AnnouncementApp.Models
{
    public class Announcement
    {   
        public int ID { get; set; }
        [Required]
        public string Content { get; set; }
        [Display(Name = "Start Date and Time")]
        public DateTime StartDate { get; set; }

        [StartEndDate("End Date and Time must be after Start Date and Time")]
        [Display(Name = "End Date and Time")]
        public DateTime EndDate { get; set; }

        [Required]
        [BindNever]
        public IdentityUser Owner { get; set; }
    }   
}

Метод контроллера:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("ID,Content,StartDate,EndDate")] Announcement announcement)
    {
        if (ModelState.IsValid)
        {
            var user = await _userManager.GetUserAsync(this.User);
            announcement.Owner = user;
            _context.Add(announcement);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(announcement);
    }

Create.cshtml

@model AnnouncementApp.Models.Announcement

@{
    ViewData["Title"] = "Create";
}

<h2>Create</h2>

<h4>Announcement</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Content" class="control-label"></label>
                <textarea asp-for="Content" class="form-control"></textarea>
                <span asp-validation-for="Content" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="StartDate" class="control-label"></label>
                <input asp-for="StartDate" class="form-control" />
                <span asp-validation-for="StartDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="EndDate" class="control-label"></label>
                <input asp-for="EndDate" class="form-control" />
                <span asp-validation-for="EndDate" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Для Announcement будет применяться [Required] как для проверки клиента, так и для таблицы базы данных.

Как показывают комментарии, вы можете рассмотреть возможность разделения Announcement на Db Model и ViewModel, вы можете определить новый AnnouncementViewModel для проверки клиента.

В качестве другой опции вы можете попробовать настроить [Required] в свободном API вместо атрибута.

Вот подробные шаги.

  1. Изменить Announcement

    public class Announcement
    {
    public int ID { get; set; }
    [Required]
    public string Content { get; set; }
    [Display(Name = "Start Date and Time")]
    public DateTime StartDate { get; set; }
    public string OwnerId { get; set; }
    //[Required]
    [BindNever]
    [ForeignKey("OwnerId")]
    public IdentityUser Owner { get; set; }
    }
    
  2. Свободный API в ApplicationDbContext

        protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    
        builder.Entity<Announcement>()
               .Property(a => a.OwnerId)
               .IsRequired();           
    }
    
  3. Контроллер

        [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("ID,Content,StartDate")] Announcement announcement)
    {
        if (ModelState.IsValid)
        {
            var user = await _userManager.GetUserAsync(User);
            announcement.Owner = user;
            _context.Add(announcement);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(announcement);
    }
    
0 голосов
/ 17 сентября 2018

Я не уверен на 100%, что вы определяете как проблему, но если вы хотите подавить ошибку «Недопустимая модель», так как вы всегда устанавливаете свойство Owner через HttpContext, вы можете использовать следующее перед проверкоймодель:

ModelState["Owner"].ValidationState = ModelValidationState.Valid

Я думаю, что ваша проблема заключается в том, что вы говорите маршрутизатору никогда не связывать «Владелец», но вы все равно говорите, что это необходимо, и поэтому ModelState потенциально сделает его недействительным.

Пока используется аннотация "Required", я не думаю, что ModelState будет проверяться без правильной установки.

Пример:

ModelState["Owner"].ValidationState = ModelValidationState.Valid
if (ModelState.IsValid)
        {
            var user = await _userManager.GetUserAsync(this.User);
            announcement.Owner = user;
            _context.Add(announcement);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(announcement);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...