La proprietà dell'oggetto dipende dagli oggetti precedenti in un elenco. Il modo migliore per andare su questo?

0

Quindi in pratica ho un oggetto con alcune proprietà al suo interno:

public MyObject
{
public string Name {get;set;}
public bool Complete {get; set;}
}

List<MyObject> myList = new List<MyObject>();

myList.Add(new MyObject("Page1", true));
myList.Add(new MyObject("Page2", false));
myList.Add(new MyObject("Page3", false));

Immagina una pagina web. Carica l'elenco di pagine sopra dal database e quindi visualizza un collegamento a ciascuna di esse.

Le pagine devono essere completate in ordine. Quindi se una pagina non è completa, la prossima pagina non può essere modificata.

Quindi in questo caso la pagina 1 è già completa. Pagina2 può essere modificato / completato. La pagina 3 non può essere modificata fino a quando la pagina 2 non è stata completata.

Sto cercando di decidere il modo migliore per implementare - Ho 3 opzioni che sto cercando di decidere tra:

1) Modifica query del database: la query corrente contiene il nome e il flag completo. Stavo pensando di aggiungere un nuovo flag che tirerà il valore dalla riga precedente, in questo modo:

SELECT Name, Complete, LAG(Complete) OVER (ORDER BY 1) as Editable
FROM @MyPages ORDER BY 1

Ma ciò è al limite della logica aziendale nel database. Mi è stato detto che è cattivo .

2) Modificare la visualizzazione della pagina Web (pagina MVC)

Il modo più semplice. Durante il looping dell'elenco, controlla la riga precedente.

Ma mi viene anche detto che la logica di business nella vista è cattiva .

3) Una sorta di nuovo modello di vista. Ma dal momento che la proprietà dipende dall'oggetto precedente in una lista, sto cercando di trovare un modo "carino" per farlo.
I migliori sono riuscito finora ...

public class MyViewModel
{
    public List<MyObject> _list;

    public bool IsEditable(int index)
    {
        if (index > 0)
        {
            if (this._list[index-1].Complete)
                return true;
            return false;
        }
        else
            return true;
    }
}

Tutti e 3 funzioneranno.
Ma recentemente ho fatto uno sforzo maggiore per fare le cose 'correttamente' piuttosto che semplicemente hackerare insieme il più veloce o la prima cosa a cui penso.

- O sto meglio demolendo l'intero oggetto e partendo da zero?
Ho già la lista delle pagine prese dal database che andava bene quando volevamo mostrare tutto e trattarli allo stesso modo. Ora è tutto rovinato ..

    
posta jb. 30.05.2017 - 17:58
fonte

2 risposte

2

Il modo in cui questo viene fatto tradizionalmente è in realtà molto semplice:

  • Il sistema di menu ha un collegamento per accedere a Pagina1, ma non offre un collegamento diretto a Pagina2 o Pagina3
  • Pagina1 ha un collegamento a Pagina2
  • Pagina2 ha un collegamento a Pagina3

Ta da. Non c'è bisogno di far bollire l'oceano.

Ora se hai bisogno di applicare rigidamente l'ordine, puoi fare quanto segue:

  1. Aggiungi codice a Pagina2 per garantire che la Pagina1 sia stata inviata. In caso contrario, reindirizza a Pagina1.
  2. Aggiungi codice a Pagina3 per garantire che la Pagina2 sia stata inviata. In caso contrario, reindirizza a Pagina2.

Di nuovo, non esattamente scienza missilistica.

Non riesco a pensare a nessun motivo per cui desideri rendere questo "generico" e utilizzare una List di pagine con flag, a meno che il tuo flusso di lavoro sia molto lungo, forse più di 10 pagine o se la pagina il flusso dovrebbe essere configurabile in fase di esecuzione o se il flusso cambia costantemente ad ogni release. Nella maggior parte dei casi, un flusso di lavoro di più pagine non ha nessuna di queste proprietà e la complessità aggiuntiva non ne vale la pena ed è probabile che confonda gli sviluppatori futuri.

    
risposta data 30.05.2017 - 19:37
fonte
2

Se il tuo flusso di lavoro è davvero così complicato e devi essere in grado di visualizzare un elenco di tutte le pagine e attivare solo quelle attualmente disponibili, ti suggerisco un approccio come questo.

  1. Crea un singolo modello che rappresenta il flusso di lavoro. Consideralo come un modulo molto lungo che un utente deve compilare.
  2. Crea dieci viste che utilizzano tutte lo stesso modello. Ogni vista corrisponde a una pagina sul modulo molto lungo.
  3. Ogni vista dovrebbe aggiornare il modello con tutti i campi che può, cioè i campi immessi nella vista corrente.
  4. Ogni vista dovrebbe anche passare attraverso tutti i campi che non può aggiornare (ad esempio i campi delle pagine precedenti). Se il tuo sito è stateless / senza sessioni, queste saranno conservate in variabili nascoste, ma potresti anche utilizzare TempData o anche Session se necessario.
  5. Ogni pagina ha precondizioni. Ad esempio, forse Pagina2 richiede cinque campi in Pagina1 per essere completamente compilato. Tutte le precondizioni devono essere valutate quando viene richiamata l'azione e, se una delle condizioni preliminari non viene soddisfatta, il browser deve essere reindirizzato alla pagina precedente.
  6. Nella pagina "master" che elenca tutti i 10 passaggi del flusso di lavoro, aggiungi il codice per controllare le precondizioni per ogni pagina e determina se abilitare o disabilitare ciascun link.
  7. È possibile implementare quanto sopra con un'azione per passo di flusso di lavoro, oppure è possibile utilizzare una singola azione con un parametro che indica il passaggio del flusso di lavoro. Ma la cosa migliore sarebbe avere una singola azione e nessun parametro; l'azione dovrebbe invece controllare tutte le precondizioni e capire quale sarà il prossimo passo in base alle informazioni mancanti. Ciò consente al tuo accoppiamento sequenziale di essere applicato endogenamente piuttosto che creare qualcosa di speciale che dovresti mantenere. Puoi aggiungere questa logica come funzione di supporto al tuo modello, ad esempio:

    class WorkflowModel
    {
        public string NextView()
        {
            if (string.IsNullOrEmpty(this.FirstName)) return "Page1";
            if (string.IsNullOrEmpty(this.Address)) return "Page2";
            if (string.IsNullOrEmpty(this.CardNumber)) return "Page3";
            return "Submit";
        }
    }
    

Quindi nel tuo metodo di azione:

    public ActionResult NextStep(WorkflowModel model)
    {
         var nextView = model.NextView;
         return View(nextView, model);
    }

E sulla tua pagina "master":

    @{ var nextView = model.NextView; }
    <A HREF="Page1" @{ (nextView < "Page1") ? "Disabled" : ""}>Page One</A>
    <A HREF="Page2" @{ (nextView < "Page2") ? "Disabled" : ""}>Page Two</A>
    <A HREF="Page3" @{ (nextView < "Page3") ? "Disabled" : ""}>Page Three</A>

Se vuoi davvero, puoi migliorare su quanto sopra con un ciclo semplice, naturalmente.

    
risposta data 30.05.2017 - 22:29
fonte

Leggi altre domande sui tag