MVC 2, IModelBinder & ValueProvider modifiche
-
22-09-2019 - |
Domanda
sto cercando di migrare verso ASP.Net MVC 2 e incontrare alcuni problemi. Qui è uno: Avevo bisogno di associare direttamente un dizionario come risultato di un post vista.
In ASP.Net MVC 1 ha funzionato perfettamente con un personalizzato IModelBinder :
/// <summary>
/// Bind Dictionary<int, int>
///
/// convention : <elm name="modelName_key" value="value"></elm>
/// </summary>
public class DictionaryModelBinder : IModelBinder
{
#region IModelBinder Members
/// <summary>
/// Mandatory
/// </summary>
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
IDictionary<int, int> retour = new Dictionary<int, int>();
// get the values
var values = bindingContext.ValueProvider;
// get the model name
string modelname = bindingContext.ModelName + '_';
int skip = modelname.Length;
// loop on the keys
foreach(string keyStr in values.Keys)
{
// if an element has been identified
if(keyStr.StartsWith(modelname))
{
// get that key
int key;
if(Int32.TryParse(keyStr.Substring(skip), out key))
{
int value;
if(Int32.TryParse(values[keyStr].AttemptedValue, out value))
retour.Add(key, value);
}
}
}
return retour;
}
#endregion
}
E 'lavorato in coppia con un certo HtmlBuilder intelligente che appare dizionario dei dati.
Il problema che incontro ora è che ValueProvider non è un Dizionario <> più, si tratta di un IValueProvider che consentono solo per ottenere valori il cui nome è noto
public interface IValueProvider
{
bool ContainsPrefix(string prefix);
ValueProviderResult GetValue(string key);
}
Questo non è davvero cool come non riesco a svolgere il mio intelligente analisi ...
Domanda:
- C'è un altro modo per ottenere tutte le chiavi?
- Sapete un altro modo per associare un insieme di elementi HTML a un dizionario
Grazie per i vostri suggerimenti
O.
Soluzione
Non credo che sarete in grado di farlo in questo modo più in MVC 2.
In alternativa, si potrebbe estendere DefaultModelBinder e sovrascrivere uno dei suoi metodi virtuali come GetModelProperties e quindi modificare il ModelName all'interno del ModelBindingContext. Un'altra opzione potrebbe essere quella di implementare un MetadataProvider personalizzato per il vostro tipo di dizionario, è possibile modificare il nome del modello anche lì.
Altri suggerimenti
Anche se questa domanda è stata segnata 'risposto' credo che la segue può essere utile. Ho avuto lo stesso problema e aveva uno sguardo al codice sorgente del System.Web.Mvc.DefaultValueProvider. Si ottiene i suoi valori dalla RouteData, la stringa di query o da una richiesta modulo di presentazione (in questo ordine esatto). Per raccogliere tutte le chiavi (che è quello che chiedete nella vostra prima domanda) Ho scritto il seguente metodo di supporto.
private static IEnumerable<string> GetKeys(ControllerContext context)
{
List<string> keys = new List<string>();
HttpRequestBase request = context.HttpContext.Request;
keys.AddRange(((IDictionary<string,
object>)context.RouteData.Values).Keys.Cast<string>());
keys.AddRange(request.QueryString.Keys.Cast<string>());
keys.AddRange(request.Form.Keys.Cast<string>());
return keys;
}
È possibile utilizzare questo metodo per enumerare le chiavi:
foreach (string key in GetKeys(controllerContext))
{
// Do something with the key value.
}