Problem z walidacją w efekcie: SqlException: Cannot insert the value NULL into column

0

Witam,

mam problem z walidacją podczas tworzenia rekordu.

Konfiguracja modelu (pole nazwa produktu):


 entityTypeBuilder
                .Property(p => p.Name)
                .IsRequired()
                .HasColumnType("varchar(255)");

Klasa kontrolera:


public async Task<IActionResult> Create([Bind("Name,Price,Id,CreatedDate,UpdatedDate")] Product product)
        {
            if (!ModelState.IsValid)
            {
                return RedirectToAction("Index");
            }

            var successful = await _productsService.CreateProduct(product);

            if (!successful)
            {
                return BadRequest("Could not add Product.");
            }

            return RedirectToAction("Index");
        }

Problem polega na tym że formularz przepuszcza mi wartości wymagane.
Po nie wypełnieniu wartości tego pola jest:
SqlException: Cannot insert the value NULL into column 'Name', table 'CRM.dbo.Products'; column does not allow nulls. INSERT fails

Input:
(zamieściłem tylko część formularza, który po submicie wykonuje metodę Create):

            <div class="form-group">
                <label asp-for="Name" class="control-label"></label>
                <input asp-for="Name" class="form-control" />
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Price" class="control-label"></label>
                <input asp-for="Price" class="form-control" />
                <span asp-validation-for="Price" class="text-danger"></span>
            </div>

Ustawiłem pole Name jako wymagane więc jeśli w powyższy input nie wpiszę wartości to czy nie powinien mi zwrócić napisu w stylu: The Name field is required?
Dodam że pole Price jest prawidłowo przechwytywane jako puste.

Wydaje mi się że jest to spowodowane tym że string Name jest typem referencyjnym. Jednak nie chcę ustawiać go w modelu jako nullable.
Dodam że ModelState.IsValid zwraca true więc wykonywana zostaje CreateProduct która rzuca wyjątkiem (dokładnie to przy zapisie -> SaveChangesAsync)
Czy jak ustawię tego stringa na nullable to nadal będę mógł ustawić go jako wymagany?
Co w tej sytuacji polecacie?

2

@travis.chigurh:

  1. Walidacja modelu nie jest tożsama z definicją encji bd. Zdefiniowałeś to, że pole ma być nienullowalne w bd, ale nie w jaki sposób ma być walidowane.
    https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-5.0
  2. Dobrą praktyką jest zdefiniowane DTO i nie przekazywanie encji do widoków. Wtedy walidujesz DTO, nie encję.

EDIT:
3. Teoretycznie możesz to zrobić w ten sposób - https://docs.microsoft.com/en-us/ef/ef6/saving/validation#fluent-api . Dla prostych CRUDów pewnie będzie ok. Ale jako zasada trzymałbym punktów 1-2 :)

0

@czesiek:

Ad1 Chodzi Ci o to że przy użyciu Fluent API dałem pole Name na wymagane ale nie określiłem minimalnej długości stringa. - Stad ModelState.IsValid jest true?
Ad2 Możesz dać przykład takiego wykorzystania DTO. jakiś code snippet lub projekt na github :)

1

@czesiek:

Dzięki za pomoc. Myślałem że fluent API to lepszy zamiennik Data Annotations.
DTO też pomocne!

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