ASP.NET MVC logika w modelu?

ASP.NET MVC logika w modelu?
SP
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 3 lata
  • Postów:57
0

Witam, miałem za zadanie zrobić prostą aplikację webową która miała wypisywać odpowiednie komunikaty, zależne od wartości wprowadzonej w formularzu. Instrukcje warunkowe które sprawdzają co trzeba wypisać napisałem w kontrolerze, lecz dowiedziałem się że "logikę" pisze się w modelu. Czy to prawda? Jeśli tak, to w jaki sposób mam w modelu sprawdzać co wypisać?

Index.cshtml

Kopiuj
@model Zadanie1CEZ.Models.Wartosc

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    @using (Html.BeginForm())
    {
        <p>Podaj liczbę: @Html.TextBoxFor(x => x.tekst)</p>

        <input type="submit" value="Wyślij liczbę" />
    }

</body>
</html>

Wartosc.cs

Kopiuj
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Zadanie1CEZ.Models
{
    public class Wartosc
    {
        public string tekst { get; set; }
    }
}

FizzBuzzControler.cs

Kopiuj
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Zadanie1CEZ.Models;

namespace Zadanie1CEZ.Controllers
{
    public class FizzBuzzController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public string Index(Wartosc wartosc)
        {

            

           

            if (Convert.ToInt32(wartosc.tekst) > 100 || Convert.ToInt32(wartosc.tekst) < 1)
            {
                return "Liczba nie jest z określonego przedziału, czyli <1,100>";
            }

            if ((Convert.ToInt32(wartosc.tekst) % 3) == 0 && (Convert.ToInt32(wartosc.tekst) % 5) == 0)
            {
                return "FizzBuzz";
            }

            if ((Convert.ToInt32(wartosc.tekst) % 3) == 0)
            {
                return "Fizz";
            }

            if ((Convert.ToInt32(wartosc.tekst) % 5) == 0)
            {
                return "Buzz";
            }




            return wartosc.tekst + " (Czyli niepodzielna ani przez 3 ani 5)";

        }
    }
}
WeiXiao
  • Rejestracja:około 9 lat
  • Ostatnio:około godziny
  • Postów:5139
1

Możesz od razu przesłać inta lub int?, aby uniknąć tego Converta lub chociaż zrobić go raz, a nie w 30 miejscach.

Jeżeli chodzi o walidacje formularzy to zainteresuj się FluentValidation

edytowany 1x, ostatnio: WeiXiao
SP
Dzięki wielkie za pokazanie tego narzędzia. tylko jeśli chodzi mi o samą logikę, to umieszczać ją w modelu? Mniej więcej tak jak w kodzie zawartym poniżej?
WeiXiao
Modelem nazywasz kontroler? nie, tam raczej nie powinieneś wkładać logiki biznesowej bo m.in niefajnie się to testuje.
SP
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 3 lata
  • Postów:57
0

Zmieniłem na coś takiego, całą logikę dałem do modelu:

Wartosc.cs

Kopiuj
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Zadanie1CEZ.Models
{
    public class Wartosc
    {
        public string tekst { get; set; }

        public string wypisz()
        {
            int result;
            bool succes = Int32.TryParse(tekst, out result);

            if (!succes)
            {
                return "Wprowadzono nieprawidłowy format danych. Podaj liczbę całkowitą";
            }

            int liczba = Convert.ToInt32(tekst);

            if (liczba > 100 || liczba < 1)
            {
                return "Liczba nie jest z określonego przedziału, czyli <1,100>";
            }

            if ((liczba % 3) == 0 && (liczba % 5) == 0)
            {
                return "FizzBuzz";
            }

            if ((liczba % 3) == 0)
            {
                return "Fizz";
            }

            if ((liczba % 5) == 0)
            {
                return "Buzz";
            }




            return tekst + " (Czyli niepodzielna ani przez 3 ani 5)";
        }
    }
}

kontroler:

Kopiuj
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Zadanie1CEZ.Models;

namespace Zadanie1CEZ.Controllers
{
    public class FizzBuzzController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public string Index(Wartosc wartosc)
        {

            return wartosc.wypisz();

        }
    }
}
WeiXiao
  • Rejestracja:około 9 lat
  • Ostatnio:około godziny
  • Postów:5139
1

Już prędzej poszedłbym w wydzielenie jakiejś klasy MyBusinessLogic, która byłaby podawana do kontrolera przez Dependency Injection i w niej wykonywał tego typu operacje, a rezultat zwracał do kontrolera, a następnie do usera.

edytowany 5x, ostatnio: WeiXiao
FU
Nie jestem przekonany czy IoC dla autora nie będzie czarną magią, wnioskując po jego pytaniu :)
WeiXiao
@Fuffu: Pewnie tak, ale w praktyce okaże się, że to jedna linijka i samo się będzie wkładać :)
FU
Z tego co rozumiem autor pisze w ASP.NET MVC (nie Core) a więc domyślnie nie ma tutaj kontenera. Instalowanie i konfiguracja mogłaby go na chwilę obecną przerosnąć.
FU
  • Rejestracja:około 12 lat
  • Ostatnio:ponad 4 lata
  • Postów:58
1

Ustalmy fakty. Model danych czy model domenowy to zupełnie coś innego niż model w rozumieniu MVC. W kontekście MVC model jest domeną aplikacji i to tam rzeczywiście powinna się znajdować logika. Zadaniem kontrolera jest wykonanie odpowiedniej logiki i zwrócenie widoku. Zatem twoja klasa Wartosc to zwykłe DTO i nie powinno tam być logiki. Stwórz klasę odpowiedzialną za tę konkretną operację biznesową, w parametrze przekazuj czego potrzebujesz i zwracaj DTO.

SP
Trochę się pogubiłem. Mógłbyś to na jakimś przykładzie wyjaśnić?
FU
  • Rejestracja:około 12 lat
  • Ostatnio:ponad 4 lata
  • Postów:58
3

Trochę się pogubiłem. Mógłbyś to na jakimś przykładzie wyjaśnić?

Na początek zdefiniuj DTO, które będzie reprezentować twój request oraz response.

Kopiuj
public class FizzBuzzRequestDTO
{
	public string Text { get; set; }
}

public class FizzBuzzResultDTO
{
	public FizzBuzzResultDTO(string text)
	{
		Text = text;
	}

	public string Text { get; }
}

Opisz swoją logikę w jakimś serwisie.

Kopiuj
public class FizzBuzzService
{
	public FizzBuzzResultDTO Validate(FizzBuzzRequestDTO request)
	{
		// tutaj walidacja i twoja logika

		return new FizzBuzzResultDTO("Wynik operacji");
	}
}

W kontrolerze wykorzystaj nowo utworzony serwis.

Kopiuj
public class FizzBuzzController : Controller
{
	[HttpPost]
	public string Index(FizzBuzzRequestDTO request)
	{
		var service = new FizzBuzzService();

		FizzBuzzResultDTO result = service.Validate(request);

		return View(result);
	}
}

Tak w uproszczeniu. W kontekście MVC twoim modelem teraz jest cała domena odpowiedzialna za wykonanie tej operacji czyli FizzBuzzService, FizzBuzzRequestDTO oraz FizzBuzzResultDTO. Zadaniem kontrolera jest tylko i wyłącznie przesterowanie do odpowiedniej logiki, pobranie wyniku i zwrócenie widoku do klienta.

edytowany 2x, ostatnio: Fuffu
SP
dzięki wielkie :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.