2012-10-02 9 views
11

Sto sviluppando una convalida lato client e lato server per una determinata proprietà viewModel.ValidationMessagePer insieme a AddModelError (chiave, messaggio). Qual è la chiave?

Nel file .cshtml ho messo questo:

@Html.DropDownListFor(model => model.EntityType.ParentId, Model.ParentTypeList, "") 
@Html.ValidationMessageFor(model => model.EntityType.ParentId) 

Nel Controller per la validazione di business

catch (BusinessException e) 
{ 
    ModelState.AddModelError("EntityType.ParentId", Messages.CircularReference); 
} 

I lavori di cui sopra come previsto: se un'eccezione viene catturato, viene visualizzato il messaggio accanto al il menu a discesa.

Tuttavia, trovo che questo modo non sia molto elegante. Nel cshtml, utilizzo un metodo per generare tutte le informazioni necessarie sulla convalida. Nel controller, devo conoscere la stringa Key esatta e usarla.

Non c'è un modo migliore per farlo?

+0

Questo link fornisce qualche ulteriore intuizione e un modo per non fare riferimento alla chiave direttamente come stringa ma come espressione: http://stackoverflow.com/questions/11090445/how-to-get-a-modelstate-key-of-an-item-in- a-list ecco un'altra risorsa ce che fornisce un metodo wrapper per la chiave Expression http://stackoverflow.com/questions/8793799/get-reference-to-object-from-c-sharp-expression – bUKaneer

risposta

21

Si potrebbe scrivere un metodo di estensione che avrà un'espressione lambda per la chiave invece di una stringa:

public static class ModelStateExtensions 
{ 
    public static void AddModelError<TModel, TProperty>(
     this ModelStateDictionary modelState, 
     Expression<Func<TModel, TProperty>> ex, 
     string message 
    ) 
    { 
     var key = ExpressionHelper.GetExpressionText(ex); 
     modelState.AddModelError(key, message); 
    } 
} 

e quindi utilizzare questo metodo:

catch (BusinessException e) 
{ 
    ModelState.AddModelError<MyViewModel, int>(
     x => x.EntityType.ParentId, 
     Messages.CircularReference 
    ); 
} 
+0

Grazie. Funziona perfettamente –

+0

Perché non è nella libreria? – UserControl

+0

@UserControl, perché non tutto può essere parte del framework. Affinché una funzionalità faccia parte del framework nei bisogni, sia scritta, testata e documentata. A volte è necessario prendere una decisione su quali funzionalità saranno incluse nella release, altrimenti non sarà possibile rilasciare :-) Quindi semplicemente Microsoft non ha trovato il tempo di implementare, testare e documentare questa funzionalità. Ecco perché non fa parte della biblioteca. –

0

si desidera che la convalida avvenga sia dal lato client che server e anche tu stai cercando una soluzione elegante, allora perché puoi provare a creare un custom ValidationAttribute.

4

seguo @Darin Dimitrov soluzione, ma voglio evitare <MyViewModel, int> così ho usato un modo diverso, ma per questo è necessario MyViewModel object variable.

public static class ModelStateExtensions 
{ 
    public static void AddModelError<TModel, TProperty>(this TModel source,   
                Expression<Func<TModel, TProperty>> ex, 
                string message, 
                ModelStateDictionary modelState) 
    { 
     var key = System.Web.Mvc.ExpressionHelper.GetExpressionText(ex); 
     modelState.AddModelError(key, message); 
    } 
} 

Come utilizzare:

catch (BusinessException e) 
{ 
    objMyViewModel.AddModelError(x => x.EntityType.ParentId, 
           Messages.CircularReference, 
           ModelState); 
} 
+4

Per me, più intuitivo sarebbe firma del metodo di estensione di: 'AddModelError (questo ModelStateDictionary modelState, modello TModel, Expression > ex, string message)'. In questo modo è possibile utilizzarlo come 'ModelState.AddModelError (model, x => x.Email," Email non valida "));' – benmccallum

Problemi correlati