MVC 2, IMODELBinder e ValueProvider Alterações
-
22-09-2019 - |
Pergunta
Estou tentando migrar para o ASP.NET MVC 2 e encontrar alguns problemas. Aqui está um: eu precisava ligar diretamente um Dicionário como resultado de um post de visualização.
No ASP.NET MVC 1, funcionou perfeitamente usando um personalizado 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
}
Funcionou em par com algum htmlbuilder inteligente que exibia dicionário de dados.
O problema que encontro agora é que ValueProvider não é mais um dicionário <>
public interface IValueProvider
{
bool ContainsPrefix(string prefix);
ValueProviderResult GetValue(string key);
}
Isso realmente não é legal, pois não posso realizar minha análise inteligente ...
Pergunta :
- Existe outra maneira de obter todas as chaves?
- Você conhece outra maneira de vincular uma coleção de elementos html a um dicionário
Obrigado por suas sugestões
O.
Solução
Acho que você não poderá mais fazê -lo dessa maneira no MVC 2.
Como alternativa, você pode estender o DefaultModelBinder e substituir um de seus métodos virtuais como getModelProperties e alterar o nome do modelo dentro do ModelBindingContext. Outra opção seria implementar um metadataprovider personalizado para o seu tipo de dicionário, você também pode alterar o nome do modelo.
Outras dicas
Embora essa pergunta tenha sido marcada 'respondida', acho que o seguinte pode ser útil. Eu tive o mesmo problema e dei uma olhada no código -fonte do sistema.web.mvc.defaultValueProvider. Ele obtém seus valores do roteiro, a sequência de consulta ou a partir de um envio de formulário de solicitação (nessa ordem exata). Para coletar todas as chaves (que é o que você faz em sua primeira pergunta), escrevi o seguinte método auxiliar.
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;
}
Você pode usar este método para enumerar sobre as chaves:
foreach (string key in GetKeys(controllerContext))
{
// Do something with the key value.
}