ASP.NET MVC:从TextBoxFor,TextBox,DropDownList和TextArea获取值

时间:2013-06-20 12:55:56

标签: asp.net-mvc textbox html-select actionlink html.textboxfor

在ASP.Net MVC中,我从另一个视图打开一个视图。第一个视图将两个值发送到第二个视图。在第二个视图中,用户可以发送电子邮件。

我遇到两个问题。

第一个问题是我从第一个视图发送的两个值没有显示在我的第二个视图中。

第二个问题是我无法通过电子邮件表单触发控制器中的电子邮件功能。

这是一个更详细的解释。

我的第一个名为ViewOne的视图正在使用控制器ControllerOne。在ViewOne中,我有以下代码来调用第二个视图ViewTwo:

@Html.ActionLink("Go to second view", "ViewTwo", "Home", new { firstval = firstval, secondval = secondval }, null)

单击ActionLink时,将调用控制器HomeController中的以下函数:

public ActionResult ViewTwo(string firstval, string secondval)
{
    MyModel model = new MyModel();
    model.firstval = firstval;
    model.secondval = secondval;
    var list = new SelectList(new[]
                                  {
                                      new {ID="1",Name="One"},
                                      new{ID="2",Name="Two"},
                                      new{ID="3",Name="Three"},
                                  },
                    "ID", "Name", 1);
    model.myList = list;
    return View(model);
}

因此,在控制器HomeController中,我尝试使用从第一个视图ViewOne获取的值填充模型myModel。

MyModel模型如下所示:

public class MyModel
{
    public string firstval { get; set; }
    public string secondval { get; set; }
    public IEnumerable<SelectListItem> myList { get; set; }

    [Required]
    [DisplayName("My name")]
    public string reporter { get; set; }

    [Required]
    [DisplayName("Description")]
    public string description { get; set; }

    [DisplayName("Dropdown")]
    public string myDropDownListValue { get; set; }
}

ViewTwo视图如下所示:

@model myapp.Models.MyModel
@{ ViewBag.Title = "Send e-mail"; }

<hgroup class="title">
    <h1>@ViewBag.Title</h1>
    <h2>@ViewBag.Message</h2>
</hgroup>

@using (Html.BeginForm("sendEmail"))
{ 
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    <fieldset>
    <legend>Send e-mail</legend>

    <p>First value:</p>
    <p>@Html.LabelFor(m => m.firstval)</p>
    <p>Second value:</p>
    <p>@Html.LabelFor(m => m.secondval)</p>
    <p>Reporter</p>
    <p>@Html.TextBoxFor(m => m.reporter)</p>
    <p>Dropdownlist</p>
    <p>@Html.DropDownListFor(m => m.myDropDownListValue, Model.myList as SelectList)</p>
    <p>Description:</p>
    <p>@Html.TextAreaFor(m => m.description, new { @cols = 150, @rows = 5})</p>
 <input type="submit" value="Send e-mail"/>

</fieldset>

}

在控制器HomeController中,它是具有ViewTwo()函数的控制器,它在上面的表格被绘制之前被触发,我有以下功能:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult sendEmail(ContactModel model) // (string keyword, string partofspeech, string reporter, string category, string description, string acceptance)
{
    // code to send email
}

所以我希望这个函数sendEmail在我提交表单时被触发。但这不会发生。单击提交按钮(标记为“发送电子邮件”)时发生的情况是视图ViewTwo被重新加载,并且控制器HomeController中的ActionResult ViewTwo()被触发。这是我的第二个(也是最大的)问题。

另外,我的第一个问题是

<p>@Html.LabelFor(m => m.firstval)</p>

不显示从第一个视图发送的值。它显示字符串“firstval”。在绘制表单之前,我可以在函数ViewTwo()中看到值从第一个视图中正确发送。

有什么想法吗?

修改

第二个问题解决了。请参阅下面的回复。

3 个答案:

答案 0 :(得分:2)

您有几个选项,通常使用回复您将使用<input type="submit" value="sendEmail" />提交表单,表单中的值将在ViewModel中表示,如:

public class EmailFormViewModel() 
{
    public string value1 {get; set;}
    public string reporter {get; set;}
    //More properties on the form
}

您的端点如下所示:

[HttpPost]
public ActionResult SendEmail(EmailFormViewModel model) 
{ 
    //Send the email
}

如果您仍想使用超链接提交表单(本机执行GET请求),您可以使用javascript捕获单击,并通过Ajax手动发送表单。

类似的东西:

$('#sendEmail').click(function(e) {
    e.preventDefault();         
    $.ajax({
        type: 'POST',
        data: $('#formId').serialize(),
        url: '/controllerName/sendemail'
    }).done(function(response) { 
        //Do something on success response
    });
});

更新

您还应该使用[ValidateAntiForgeryToken]修饰您的帖子操作sendEmail,并在表单中添加@Html.AntiForgeryToken()。这有助于防止跨站点伪造请求。

您可以像这样构建表单,端点和模型:

@using (Html.BeginForm("sendEmail"))
{ 
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()
    <p>@Html.LabelFor(m => m.value1)</p>
    <p>@Html.EditorFor(m => m.value1)</p>
    <p>@Html.LabelFor(m => m.reporter)</p>
    <p>@Html.EditorFor(m => m.reporter)</p>
    <p>@Html.LabelFor(m => m.myDropDownListValue)</p>
    <p>@Html.DropDownListFor(m => m.myDropDownListValue, Model.myList as SelectList)</p>
    <p>@Html.LabelFor(m => m.myTextAreaValue)</p>
    <p>@Html.TextAreaFor(m => m.myTextAreaValue, new { @cols = 150, @rows = 5})</p>
    <input type="submit" value="Send Email"/>
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SendEmail(myModel model) 
{ 
    //Send the email
}

public class myModel
{
    public IEnumerable<SelectListItem> myList { get; set; }
    [DisplayName('Value 1')]
    public string value1 { get; set; }
    [DisplayName('Reporter')]
    public string reporter { get; set; }
    [DisplayName('Text Area')]
    public string myTextAreaValue { get; set; }
    [DisplayName('Dropdown')]
    public string myDropDownListValue { get; set; }
}

只要您已经在同一个控制器上,它就会使用帖子中的表单数据回发到/controllername/sendemail。您还应该在模型上查找属性,例如,可以强制执行描述和验证。 Check here for more details,它的MVC 2,但仍然相关。

答案 1 :(得分:0)

如果您真的希望能够获取值而不是POST它们,请将表单的操作更改为GET并将目标更改为sendEmail

删除ActionLink并将其替换为简单的提交按钮

我知道你说你想保留ActionLink,但这将实现同样的目标

答案 2 :(得分:0)

我设法解决了我的第一个问题。一旦我指定函数sendEmail所在的控制器,该代码最终被触发。像这样:

@using (Html.BeginForm("sendEmail", "Home"))

现在,如果我只能找出原因

<p>@Html.LabelFor(m => m.firstval)</p>

不工作然后我安全回家。

它实际打印出字符串“firstval”,而不是取我在模型中设置的字符串变量firstval的值。 (有关更详细的说明,请参阅我的第一篇文章)。

修改

我修复了最后一个问题。非常令人担忧的是,使用LabelFor的上述代码不起作用。但如果我这样做:

<p>@Model.firstval</p>

然后我得到了价值。但是在提交表单时它不会被发送回控制器。但我解决了:

@Html.HiddenFor(m => m.firstval)

所以HiddenFor对我有用,LabelFor没有。

案件结案。我把“解决的复选标记”扔给那些在上面给了我所有帮助的人。他做得很棒。但真正的解决方案是在这篇文章中。 :)