Problem z walidacją komentarza

0

Cześć. Poznaje Fluent Api i mam taki problem nie wiem czemu. Nie wyświetlają mi się errory w tym projekcie. Formularz mimo wszystko nie przpuszcza forumularza tzn że chyba filtry działają. Wiecie co może być tego przyczyną ?

        [HttpPost]
        public ActionResult AddBook(HttpPostedFileBase file, Book book)
        {
                BookValidation val = new BookValidation();
                ValidationResult model = val.Validate(book);
                

                if(model.IsValid == false)
                {
                    foreach (ValidationFailure _error in model.Errors)
                    {
                        ModelState.AddModelError(_error.PropertyName, _error.ErrorMessage);
                    }

                    AddBookViewModel vm = new AddBookViewModel()
                    {
                        Book = book,
                        Categories = categoryService.Categories
                    };
                    return View(vm);
            }

                bookService.AddBook(file,book);
                return RedirectToAction("Index", "Home");
        }
    public class BookValidation : AbstractValidator<Book>
    {
        public BookValidation()
        {
            RuleFor(x => x.Title).NotEmpty().Length(3,20).WithMessage("Pole Tytuł jest wymagane");
            RuleFor(x => x.ImageUrl).NotNull().WithMessage("Ścieżka do obrazka jest wymagane");
            RuleFor(x => x.Year).NotNull().WithMessage("Rok jest wymagany");
            RuleFor(x => x.NumberOfCopies).NotNull().WithMessage("Numer kopii jest wymagany");
            RuleFor(x => x.Cost).NotNull().WithMessage("Koszt jest wymagany");
        }
    }
@model LMS.WebUI.Models.AddBookViewModel

@{
    ViewBag.Title = "AddBook";
}

<h2>AddBook</h2>


@using (Html.BeginForm("AddBook", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.ValidationSummary()

    <div class="form-horizontal">
        <h4>Book</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Book.Title, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Book.Title, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Book.Title, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Book.CategoryId, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(m => m.Book.CategoryId, Model.CategoriesItems, "Wybierz opcję", new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Book.CategoryId, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Book.Author, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Book.Author, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Book.Author, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Book.Year, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Book.Year, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Book.Year, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Book.Cost, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Book.Cost, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Book.Cost, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Book.NumberOfCopies, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Book.NumberOfCopies, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Book.NumberOfCopies, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Book.ImageUrl, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                <input type="file" name="file" id="file" />
                @Html.ValidationMessageFor(model => model.Book.ImageUrl, "", new { @class = "text-danger" })
            </div>
        </div>

        <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>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

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

Z góry dziękuje za pomoc :)

0

Na widoku masz ViewModel a w akcji przyjmujesz model?

0

Tak kurcze ale ten ViewModel wygląda tak:

    public class AddBookViewModel
    {
        public Book Book { get; set; }
        public IEnumerable<Category> Categories { get; set; }
        public IEnumerable<SelectListItem> CategoriesItems
        {
            get
            {
                var allItems = Categories.Select(f => new SelectListItem
                {
                    Value = f.CategoryId.ToString(),
                    Text = f.Name
                });

                return allItems;
            }
        }
    }
2

Tu masz oficjalny "tutorial", jak pogodzić FluentValidation z ASP.NET MVC: https://fluentvalidation.net/mvc5
Tak jak piszą poprzednicy: w akcji kontrolera powinieneś przyjmować AddBookViewModel, a nie encję Book. Do tego AddBookViewModel powinieneś udekorować atrubutem [Validator(typeof(AddBookViewModelValidator))] (który powinieneś sobie napisać, bo na razie masz jedynie walidator encji Book). Do tego w Application_Start powinieneś mieć FluentValidationModelValidatorProvider.Configure();. Jeśli już robisz walidację w metodzie, a nie w filtrze (nie jest to dobra praktyka), to powinieneś mieć coś w stylu:

if (!ModelState.IsValid) 
{
    // jeśli masz jakiś dropdown, którego wartości są zależne od tego, co jest w bazie, 
    // to tu możesz ponownie dodać SelectListItems do ViewModelu
	return View("Add", viewModel); // AddBookViewModel przyjmujesz jako argument akcji kontrolera
}
// ...

BTW we ViewModelu AddBookViewModel nie powinieneś mieć encji Book! Powinieneś mieć właściwości typu Title, Description itd.

[Validator(typeof(AddBookViewModelValidator))]
public class AddBookViewModel
    {
        public string Title { get; set; }
        public string Description { get; set; }
        public int CategoryId { get; set; }
        public IEnumerable<SelectListItem> Categories { get; set; } // Wypełniasz tę listę np. w kontrolerze
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1