ASP.NET MVC动态表单

27

有人能否建议一种使用ASP.NET MVC开发动态表单的好方法?

页面上有级联下拉框(下拉框中的选项取决于前一个下拉框中选择的值)。

所有值都来自数据库。

我如何使用ASP.NET MVC实现这种行为?

当提交表单时,当然我想在控制器中接收所有值。

6个回答

21

您可以使用FormCollection作为参数来接收来自表单的所有数据:

[HttpPost]
public ActionResult ActionName(FormCollection collection)
{
    //collection["inputName"];
}

在我看来,这绝对是最简单的解决方案。为什么这个答案不像其他答案那样受欢迎?它是否存在任何问题需要了解? - einord
2
它是IFormCollection。 - Mosta

13

你可以很容易地使用我的FormFactory库来实现此功能。

默认情况下,它会反射一个视图模型以生成一个PropertyVm[]数组:

```

var vm = new MyFormViewModel
{
    OperatingSystem = "IOS",
    OperatingSystem_choices = new[]{"IOS", "Android",};
};
Html.PropertiesFor(vm).Render(Html);

但是您也可以通过编程的方式创建属性,因此您可以从数据库加载设置,然后创建 PropertyVm

这是来自 Linqpad 脚本的片段。

```

//import-package FormFactory
//import-package FormFactory.RazorGenerator


void Main()
{
    var properties = new[]{
        new PropertyVm(typeof(string), "username"){
            DisplayName = "Username",
            NotOptional = true,
        },
        new PropertyVm(typeof(string), "password"){
            DisplayName = "Password",
            NotOptional = true,
            GetCustomAttributes = () => new object[]{ new DataTypeAttribute(DataType.Password) }
        }
    };
    var html = FormFactory.RazorEngine.PropertyRenderExtension.Render(properties, new FormFactory.RazorEngine.RazorTemplateHtmlHelper());   

    Util.RawHtml(html.ToEncodedString()).Dump(); //Renders html for a username and password field.
}

这里有一个演示站点,展示了各种功能的示例,例如嵌套集合、自动完成、日期选择等等。


嗨,1)在这个片段中 using (var form = Html.FormForAction((HomeController c, string p0, string p1, bool p2, string p3) => c.SignIn(p0, p1, p2, p3))) 有4个变量,但动作只需要3个变量,2)第二个表单中的提交是如何执行的,请您可否详细展开文档说明?3)我该如何使用Lat Long、Fa-Icons? - aggie
1
@AdnanNiloy 你需要创建一个中间自定义类型(例如FieldDefinition),来保存你的数据并将其存储在数据库表中。然后,你可以从数据库中提取这些数据,并使用它们来创建PropertyVm对象。 - mcintyre321
@mcintyre321,从数据库中获取的数据,是否可以实现嵌套模型,例如国家>州>城市? - Maulik Modi
@maulikmodi 使用标准的 FF 控件,如果您愿意将所有数据加载到页面中,则可以轻松地进行嵌套控件。要使惰性获取的数据驱动嵌套控件可能需要一些思考。 - mcintyre321
@MaulikModi 是的 - 遍历您的 JObject 并将其转换为 List<PropertyVm>。 - mcintyre321
显示剩余2条评论

11
如果您需要在表单中添加一些动态字段,那么最好的方法是使用一些先进的JavaScript框架,如Angular, Backbone, Knockout等。
如果您需要一些更简单或更复杂的东西,那么只使用Knockout就足够了。对于更高级的情况,我会推荐Angular,但这是我的个人偏好。
下面是使用Knockout实现动态表单的一个简单示例:

var model = {
    users: ko.observableArray(),
    addUser: function() {
        this.users.push({ name: ko.observable() });
    }
};

ko.applyBindings(model);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="foreach: users">
    <input type="text" data-bind="value: name" /><br />
</div>
<button data-bind="click: addUser">Add user</button>

<ul data-bind="foreach: users">
    <li data-bind="text: name"></li>
</ul>

那么,ASP.NET MVC呢?

这更加棘手。也许最好、最简单的方法是使用Ajax并将JSON发布到ASP.NET MVC操作。首先,您需要从表单中获取一个JSON对象。使用knockout非常简单:

var json = ko.toJSON(model);

现在,我们知道如何从表单中获取JSON数据,下一步是将您的数据发送到一个操作。jQuery非常适合这个任务:
$.ajax({
    type: "POST", 
    url: "@Url.Action("AddUser")",
    data: ko.toJSON(model).users, // Serialize to JSON and take users array
    accept: 'application/json',
    success: function (data) { alert("Done!"); } // Your success callback
});

在我们的情况下,我们基本上发送一个字符串数组,因此ASP.NET MVC操作应该如下所示:
[HttpPost]
public JsonResult AddUser(List<string> users)
{
    return Json(data); // return something
}

这绝对不是实现动态表单的唯一选项,但我认为它非常有效。希望能有所帮助。

1
嗨,我正在尝试构建一个动态视图,其中字段和控制选项来自数据库(例如,如果是下拉菜单,是否可选以及图像上传等)... knockoutjs是否能胜任这项工作?我完全不熟悉它。如果可能的话,希望能得到一些帮助或示例。 - Zaki
6
@Zaki,我觉得你想用Knockout来进行下拉绑定,但同时用jQuery向服务器发送ajax请求。我建议你先设计Knockout页面模型,然后再开发jQuery程序。 - Andrei
我尝试了你的代码,但它没有起作用。 您是否在属性上缺少User类名称: { name:'Users ['+ $ index()+'] .User'? 服务器上的Name属性始终为null。 - Onaiggac
@Onaiggac 很好的发现!我忘记了函数ko.applyBindings的第二个参数。请看更新!谢谢你让我知道! - Andrei
@AndreiMikhalevich 我错了,你不是缺少User类名,而是属性名attr: { name: 'Users[' + $index() + '].Name' }。现在它运行得很好。我会尝试第二个参数。 - Onaiggac
@AndreiMikhalevich,使用新代码后,我仍然需要在attr末尾添加.Name。如果没有它,我会得到错误,而加上.Name后则是正常的 - Onaiggac

2
我会为下拉选项和额外字段创建部分视图。然后创建控制器,根据下拉菜单的值返回相应的html部分。
public class FormFieldsController : Controller
{
    public ActionResult Index(string dropDownOption)
    {
        if(dropDownOption == "Option1")
           return PartialView("PartialForOption1");
       etc.//
    }
}

然后只需使用 jQuery Ajax 调用它,并在下拉菜单更改时将当前表单附加到操作结果。

$.ajax("/FormFields/Index",
    {
        async: false,
        data: { dropDownOption: $('#dropDownId').value()},
        success: function(data) {
            if (callback == null) {
                $("#form").append(data);
            } else {
                callback(data);
            }
        },
        error: function() {
            alert('Error');
        },
        type: 'GET',
        timeout: 10000
    }
);

0

0

1
这里提供了代码源文件,可以下载:http://mvcdynamicforms.codeplex.com/downloads/get/104026 - Soner
7
嗨,Soner,我该如何构建像这样的模型:class MyModel {public Form FormData{get;set;}, public string Name{get;set} },我在控制器中总是得到空值(null)的表单? - Andrei
1
如果你在询问创建模型,那么你做得很对。但是,如果你在询问<form> </form>内部的内容,你必须为“form”写一个名称,并在控制器中调用你的表单名称。 - Soner
请查看我的问题更新。我在那里描述了我的问题。 - Andrei
很抱歉没有提供更多帮助。 - Soner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接