MVC Visualizza fortemente tipita e proprietà di impostazione del server prima di inviare a livelli inferiori?

StackOverflow https://stackoverflow.com/questions/7389635

  •  29-10-2019
  •  | 
  •  

Domanda

Ho un'applicazione a strati che invia comandi al livello aziendale (in realtà, l'applicazione si basa su Framework NCQRS, ma non penso che sia importante qui).

Un comando sembra questo:

public class RegisterUserCommand : CommandBase
{
    public string UserName { get; set; }
    public string Email{ get; set; }
    public DateTime RegistrationDate { get; set; }
    public string ApiKey {get; set;} // edit
}

Non esiste una logica in questa classe, solo dati.

Voglio che gli utenti digitassero il loro nome utente, e -mail e voglio che il sistema utilizzi la data corrente per creare il comando.

Cos'è meglio tra:

  1. Creare una vista fortemente digitata in base al registerUserCommand, quindi iniettare la data e la chiave API appena prima di inviarla al livello aziendale?

  2. Creare una classe RegisterUserviewModel, creare la vista con questa classe e creare l'oggetto di comando in base all'ingresso di visualizzazione?

Ho scritto il seguente codice (per la soluzione n ° 2):

public class RegisterController : Controller
{
    //
    // GET: /Register/

    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(RegisterUserViewModel registrationData)
    {

        var service = NcqrsEnvironment.Get<ICommandService>();
        service.Execute(
            new RegisterUserCommand
            {
                RegistrationDate = DateTime.UtcNow,
                Email= registrationData.Email,
                UserName= registrationData.Name,
                ApiKey = "KeyFromConfigSpecificToCaller" // edit
            }
            );

        return View();
    }


    public class RegisterUserViewModel
    {
        [Required]
        [StringLength(16)]
        public string Name { get; set; }
        [Required]
        [StringLength(64)]
        public string Email{ get; set; }
    }
}

Questo codice funziona ... ma mi chiedo se scelgo il modo corretto ...

Grazie per i consigli

Modificare Dato che DateTime sembra causare fraintendimenti, ho aggiunto un'altra proprietà "Apikey", che dovrebbe anche essere impostata sul lato server, dal livello Web (non dal livello di comando)

EDIT 2 Prova il suggerimento Erik e implementa la prima soluzione che ho immaginato:

[HttpPost]
public ActionResult Index(RegisterUserCommand registrationCommand)
{

    var service = NcqrsEnvironment.Get<ICommandService>();
    registrationCommand.RegistrationDate = DateTime.UtcNow;
    registrationCommand.ApiKey = "KeyFromConfigSpecificToCaller";
    service.Execute(
        registrationCommand
        );

    return View();
}

... è accettabile?

È stato utile?

Soluzione

Penso che starai meglio con l'opzione n. 2, in cui avresti un ViewModel separato e un comando. Sebbene possa sembrare ridondante (in una certa misura), i tuoi comandi sono davvero messaggi dal tuo server web al gestore dei comandi. Quei messaggi non possono essere formattati come il tuo ViewModel, né dovrebbero esserlo. E se stai usando NCQRS così com'è, dovresti quindi mappare i tuoi comandi ai metodi e ai costruttori AR.

Anche se potrebbe farti risparmiare un po 'di tempo, penso che tu ti buchi per modellare il tuo dominio dopo i tuoi modi di vista, e non dovrebbe essere il caso. I tuoi modi di vista dovrebbero essere un riflesso di ciò che il tuo utente sperimenta e vede; Il tuo dominio dovrebbe essere un riflesso delle regole e delle conoscenze aziendali e non si riflette sempre nel tuo punto di vista.

Può sembrare un po 'più di lavoro ora, ma fai un favore e mantieni i tuoi comandi separati dai tuoi modelli di vista. Ti ringrazierai più tardi.

Spero che questo aiuti. Buona fortuna!

Altri suggerimenti

Consiglierei di metterlo nel costruttore della classe RegisterUserCommand. In questo modo il comportamento predefinito è sempre quello di impostarlo su datetime.utcnow e se è necessario impostarlo su qualcosa di esplicito puoi semplicemente aggiungerlo all'inizializzatore dell'oggetto. Ciò aiuterà anche negli scenari in cui stai usando questa classe in altre parti del tuo progetto e dimentichi di impostare esplicitamente la registrazione.

public class RegisterUserCommand : CommandBase
{
    public string UserName { get; set; }
    public string Email{ get; set; }
    public DateTime RegistrationDate { get; set; }

    public RegisterUserCommand()
    {
        RegistrationDate = DateTime.UtcNow;
    }
}

E il controller

public class RegisterController : Controller
{
    //
    // GET: /Register/

    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(RegisterUserViewModel registrationData)
    {

        var service = NcqrsEnvironment.Get<ICommandService>();
        service.Execute(
            new RegisterUserCommand
            {
                Email= registrationData.Email,
                OpenIdIdentifier = registrationData.OpenIdIdentifier
            }
            );

        return View();
    }


    public class RegisterUserViewModel
    {
        [Required]
        [StringLength(16)]
        public string Name { get; set; }
        [Required]
        [StringLength(64)]
        public string Email{ get; set; }
    }
}

Userei il numero 1 e userei il System.ComponentModel.DataAnnotations.MetadataType per validazione.

Ho creato un esempio (risposta) per un'altra domanda SO Qui.

Ciò ti consente di mantenere il tuo modello in un'altra libreria, convalidare i campi e mostrare i campi come faresti le classi interne/private con dataNnotazioni. Non sono un grande fan della creazione di una classe completamente separata per una visione che non ha alcun valore aggiuntivo mentre è necessario riportare i dati in un'altra classe. (Se avessi valori aggiuntivi come i valori dell'elenco a discesa o valori predefiniti, penso che avrebbe senso).

Invece di

[HttpPost]
public ActionResult Index(RegisterUserViewModel registrationData)
{

    var service = NcqrsEnvironment.Get<ICommandService>();
    service.Execute(
        new RegisterUserCommand
        {
            RegistrationDate = DateTime.UtcNow,
            Email= registrationData.Email,
            UserName= registrationData.Name,
            ApiKey = "KeyFromConfigSpecificToCaller" // edit
        }
        );

    return View();
}

Puoi avere

[HttpPost]
public ActionResult Index(RegisterUserCommand registrationData)
{

    var service = NcqrsEnvironment.Get<ICommandService>();

    registrationData.ApiKey = "KeyFromConfigSpecificToCaller";

    service.Execute(registrationData);

    return View();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top