MVC 2、IModelBinder &价值提供者变更

发布于 2024-08-23 03:58:14 字数 1906 浏览 12 评论 0原文

我正在尝试迁移到 ASP.Net MVC 2 并遇到一些问题。 这是其中之一: 我需要直接绑定一个字典作为查看帖子的结果。

在 ASP.Net MVC 1 中,它使用自定义的 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
}

它与一些显示数据字典的智能 HtmlBuilder 配合使用。

我现在遇到的问题是 ValueProvider 不是一个 Dictionary<>不再是了,它是一个 IValueProvider,只允许获取名称已知的值

public interface IValueProvider
{
    bool ContainsPrefix(string prefix);
    ValueProviderResult GetValue(string key);
}

这真的不酷,因为我无法执行智能解析...

问题:

  1. 是否有另一种方法来获取所有键?
  2. 您知道将 HTML 元素集合绑定到字典的另一种方法吗?

感谢您的建议

O.

I'm trying to migrate to ASP.Net MVC 2 and meet some issues.
Here is one :
I needed to bind directly a Dictionary as result of a view post.

In ASP.Net MVC 1 it worked perfectly using a custom 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
}

It worked in pair with some smart HtmlBuilder that displayed dictionary of data.

The problem I meet now is that ValueProvider is not a Dictionary<> anymore, it's a IValueProvider that only allow to get values whose name is known

public interface IValueProvider
{
    bool ContainsPrefix(string prefix);
    ValueProviderResult GetValue(string key);
}

This is really not cool as I cannot perform my smart parsing...

Question :

  1. Is there another way to get all keys ?
  2. Do you know another way to bind a collection of HTML elements to a Dictionary

Thanks for your suggestions

O.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

长发绾君心 2024-08-30 03:58:14

尽管这个问题已被标记为“已回答”,但我认为以下内容可能会有所帮助。
我遇到了同样的问题,并查看了 System.Web.Mvc.DefaultValueProvider 的源代码。它从 RouteData、查询字符串或请求表单提交(按照确切的顺序)获取其值。为了收集所有密钥(这是您在第一个问题中所要求的),我编写了以下辅助方法。

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;
}

您可以使用此方法来枚举键:

foreach (string key in GetKeys(controllerContext))
{
    // Do something with the key value.
}

Though this question has been marked 'answered' I think the following may be helpful.
I had the same problem and had a look at the source code of the System.Web.Mvc.DefaultValueProvider. It gets its values from the RouteData, the query string or from a request form submission (in that exact order). To collect all the keys (which is what you ask for in your first question) I wrote the following helper method.

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;
}

You can use this method to enumerate over the keys:

foreach (string key in GetKeys(controllerContext))
{
    // Do something with the key value.
}
抽个烟儿 2024-08-30 03:58:14

我认为在 MVC 2 中您将无法再这样做。
或者,您可以扩展 DefaultModelBinder 并重写其虚拟方法之一(例如 GetModelProperties),然后更改 ModelBindingContext 内的 ModelName。另一种选择是为您的字典类型实现自定义 MetadataProvider,您也可以在那里更改模型名称。

I don't think you'll be able to do it this way anymore in MVC 2.
Alternatively, you could extend DefaultModelBinder and override one of its virtual methods like GetModelProperties and then change the ModelName inside the ModelBindingContext. Another option would be to implement a custom MetadataProvider for your Dictionary type, you can change the model name there as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文