2011-02-23 80 views
99

我有一个MVC控制器具有此操作方法:如何从HTTPPOST,字典或?中检索表单值

[HttpPost] 
public ActionResult SubmitAction() 
{ 
    // Get Post Params Here 
... return something ... 
} 

形式是一个不平凡的形式,用一个简单的文本。

问题

我如何获得的参数值?

我不是从一个视图张贴,这个帖子来自外部。我假设有一个我有权访问的键/值对的集合。

我试过Request.Params.Get("simpleTextBox");,但它返回错误“抱歉,处理您的请求时发生错误。”。

回答

125

你可以有你的控制器动作,像是一个对象,它会反映形式输入名称,默认模式粘结剂将自动为您创建该对象:

[HttpPost] 
public ActionResult SubmitAction(SomeModel model) 
{ 
    var value1 = model.SimpleProp1; 
    var value2 = model.SimpleProp2; 
    var value3 = model.ComplexProp1.SimpleProp1; 
    ... 

    ... return something ... 
} 

另一个(显然不美观)的方法是:

[HttpPost] 
public ActionResult SubmitAction() 
{ 
    var value1 = Request["SimpleProp1"]; 
    var value2 = Request["SimpleProp2"]; 
    var value3 = Request["ComplexProp1.SimpleProp1"]; 
    ... 

    ... return something ... 
} 
+4

我只是想指出,你失去了编译器的备份选项2.如果模型更改,编译器将无法捕获相关控制器中的更改。方案2有很好的案例,但我不鼓励广泛使用。 – 2016-03-02 15:06:30

+0

有时你需要丑陋的东西,当你已经知道最佳实践是什么时,有好的选择 – 2016-05-05 20:22:07

+0

作为还在学习网点的人,为什么第二种方式更丑陋? – Goose 2017-01-12 18:16:31

94

简单地说,你可以使用FormCollection这样的:

[HttpPost] 
public ActionResult SubmitAction(FormCollection collection) 
{ 
    // Get Post Params Here 
string var1 = collection["var1"]; 
} 

您还可以使用一类,被映射与表单值,和asp.net的MVC引擎自动地填充它:

//Defined in another file 
class MyForm 
{ 
    public string var1 { get; set; } 
} 

[HttpPost] 
public ActionResult SubmitAction(MyForm form) 
{  
    string var1 = form1.Var1; 
} 
+0

我喜欢上课解决方案简单易懂 – 2016-08-07 16:03:41

29

的答案是非常好的,但存在的MVC和最新发布的另一种方式。 NET,我真的很喜欢使用,而不是“老派”FormCollection和请求键。


考虑一个包含在表单标签中的HTML代码片段,它可以执行AJAX或FORM POST。

<input type="hidden" name="TrackingID" 
<input type="text"  name="FirstName" id="firstnametext" /> 
<input type="checkbox" name="IsLegal" value="Do you accept terms and conditions?" /> 

你的控制器实际上将解析表单数据,并尝试将它提供给你作为定义类型的参数。我包括复选框,因为它是一个棘手的问题。如果选中,则返回文本“on”;如果未选中,则返回null。需求虽然是这些已定义的变量必须存在(除非可为空(请记住,虽然string是可空的)),否则AJAX或POST返回将失败。

[HttpPost] 
public ActionResult PostBack(int TrackingID, string FirstName, string IsLegal){ 
    MyData.SaveRequest(TrackingID,FirstName, IsLegal == null ? false : true); 
} 

您也可以将背面的模型,而无需使用任何剃刀助手。我发现这是需要一些时间的。

public Class MyModel 
{ 
    public int HouseNumber { get; set; } 
    public string StreetAddress { get; set; } 
} 

的HTML标记将只是......

<input type="text" name="MyHome.HouseNumber" id="whateverid" > 

和控制器(剃刀引擎)将拦截表单变量“是MyHome”,并尝试建立起来,并将其转换为为MyModel。

[HttpPost] 
public ActionResult PostBack(MyModel MyHome){ 
    postBack.HouseNumber; //The value user entered 
    postBack.StreetAddress; //the default value of NULL. 
} 

当一个控制器期望一个Model时,你不必定义所有的字段,因为解析器会将它们保留为默认值,通常为NULL。好的是你可以在Mark-up上混合和匹配各种模型,并且后期解析将尽可能地填充。您不需要在页面上定义模型或使用任何助手。

提示:控制器中参数的名称是在HTML标记“name =”中定义的名称 而不是Model的名称!


使用List<>在其加价更复杂一些。

<input type="text" name="MyHomes[0].HouseNumber" id="id"   value="0"> 
<input type="text" name="MyHomes[1].HouseNumber" id="whateverid-x" value="1"> 
<input type="text" name="MyHomes[2].HouseNumber"     value="2"> 
<input type="text" name="MyHomes[3].HouseNumber" id="whateverid22" value="3"> 

列表上的索引<>必须始终为零,并且是连续的。 0,1,2,3。

[HttpPost] 
public ActionResult PostBack(List<MyModel> MyHomes){ 
    int counter = MyHomes.Count() 
    foreach(var home in MyHomes) 
    { ... } 
} 

使用IEnumerable<>基于非零和非循序索引后回来。我们需要添加一个额外的隐藏输入来帮助活页夹。

<input type="hidden" name="MyHomes.Index" value="278"> 
<input type="text" name="MyHomes[278].HouseNumber" id="id"  value="3"> 

<input type="hidden" name="MyHomes.Index" value="99976"> 
<input type="text" name="MyHomes[99976].HouseNumber" id="id3" value="4"> 

<input type="hidden" name="MyHomes.Index" value="777"> 
<input type="text" name="MyHomes[777].HouseNumber" id="id23" value="5"> 

和代码只需要使用IEnumerable和调用ToList()

[HttpPost] 
public ActionResult PostBack(IEnumerable<MyModel> MyHomes){ 
    int counter = MyHomes.ToList().Count() 
    foreach(var home in MyHomes) 
    { ... } 
} 

建议使用单一模型或视图模型(模型contianing其他模型来创建一个复杂的“查看'型号)每页。如所提出的混合和匹配可能被认为是不好的做法,但只要它有效并且可读性不坏。然而,它证明了剃刀引擎的强大和灵活性。因此,如果您需要放弃某项任意操作或覆盖Razor帮助程序中的其他值,或者不想自己制作帮助程序,对于使用一些不寻常的数据组合的单一表单,您可以快速使用这些接受额外数据的方法。

+2

最后有人解释清楚 – 2016-09-26 14:05:04

+0

使用索引选项很模糊。谁在上帝的绿色地球上知道会使用它,或者它甚至存在?!但是,我很高兴我找到了这篇文章。这将节省大量的网络流量。 – 2016-11-22 00:14:19

+1

这对我有用,但只有在我将改为@ Html.Hidden(“myId”) – radkan 2017-02-02 22:56:10

8

如果您想直接从Http请求获取表单数据,没有任何模型绑定或FormCollection您可以使用此:

[HttpPost] 
public ActionResult SubmitAction() { 

    // This will return an string array of all keys in the form. 
    // NOTE: you specify the keys in form by the name attributes e.g: 
    // <input name="this is the key" value="some value" type="test" /> 
    var keys = Request.Form.AllKeys; 

    // This will return the value for the keys. 
    var value1 = Request.Form.Get(keys[0]); 
    var value2 = Request.Form.Get(keys[1]); 
} 
+1

请注意,这可能是一个糟糕的形式(没有双关语意图),但有时你只是想要表单值,你不能干净地改变函数签名。这是适合我特殊情况的唯一解决方案。 – Ryan 2016-07-27 02:33:10

+0

如何使用这些静态引用对此方法进行单元测试?当涉及到测试时,FormCollection会更受欢迎。 – 2017-06-30 15:20:12

+0

@KeesdeWit如果您阅读之前的评论,这不是最好的方法,但有时用作解决方法。为了进行单元测试,可能你可以模拟'Request'并将其注入到方法中。 – 2017-06-30 16:30:48