动态表单构建和传递查询参数

时间:2012-01-19 16:10:14

标签: asp.net-mvc-3 oauth query-parameters formcollection formbuilder

我正在处理一个基于数据库中的某些元数据表动态生成的表单。我创建了输入标签,其名称类似于setting_1,setting_53,setting_22,其中数字是元数据的主键。由于内容是动态的,我使用FormCollection作为POST请求的唯一参数。

问题1:GET请求是否有类似FormCollection的类?我想直接访问查询参数。

问题2:如果我需要传递这些查询参数,是否有一种简单/安全的方式来构建我的网址?

我最关心的一个问题是,某些设置是通过OAuth填充的,因此用户将被重定向到外部页面。我必须将查询字符串作为“状态”传递,一旦用户返回,我将需要恢复。我将需要使用此状态来获取用户在表单输入过程中停止的位置。我需要一个非常简单的机制来传递查询参数。

是否有人处理过这样的动态网页?传递这些页面是否有良好的模式和做法?

1 个答案:

答案 0 :(得分:1)

好吧,你当然可以在控制器动作中查看Request.QueryString

但如果是我这样做的话,我会写一个自定义模型绑定器。

这是一个样本模型绑定器。我没有测试过这个!

public class MyModelBinder: DefaultModelBinder
{
    private static void BindSettingProperty(
        ControllerContext controllerContext, 
        ModelBindingContext bindingContext, 
        PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.PropertyType != typeof(IDictionary<string, string>))
        {
            throw new InvalidOperationException("This binder is for setting dictionaries only.");
        }
        var originalValue = propertyDescriptor.GetValue(bindingContext.Model) as IDictionary<string, string>;
        var value = originalValue ?? new Dictionary<string, string>();
        var settingKeys = controllerContext.HttpContext.Request.QueryString.AllKeys.Where(k => k.StartsWith("setting_", StringComparison.OrdinalIgnoreCase));
        foreach (var settingKey in settingKeys)
        {
            var key = settingKey.Substring(8);
            value.Add(key, bindingContext.ValueProvider.GetValue(settingKey).AttemptedValue);
        }
        if (value.Any() && (originalValue == null))
        {
            propertyDescriptor.SetValue(bindingContext.Model, value);
        }
    }

    protected override void BindProperty(
        ControllerContext controllerContext, 
        ModelBindingContext bindingContext, 
        PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.Name.StartsWith("setting_", StringComparison.OrdinalIgnoreCase)
        {
            BindSettingProperty(controllerContext, bindingContext, propertyDescriptor);
        }
        else
        {
            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
        }
    }
}