0

在 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() 中看到该值是从第一个视图正确发送的。

有任何想法吗?

编辑:

第二个问题解决了。请看我下面的回复。

4

3 回答 3

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

更新:

您还应该使用 sendEmail 装饰您的帖子操作,并在表单中[ValidateAntiForgeryToken]添加一个。@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帖子中的表单数据。您还应该查找模型上的属性,例如,您可以强制执行描述和验证。在这里查看更多详细信息,它的 MVC 2 但仍然相关。

于 2013-06-20T13:23:35.530 回答
0

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

删除 ActionLink 并用一个简单的提交按钮替换它

我知道你说过你想保留 ActionLink,但这会达到同样的效果

于 2013-06-20T13:22:49.213 回答
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 没有。

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

于 2013-06-23T17:55:46.913 回答