将数据返回到部分视图

时间:2011-10-26 20:16:33

标签: asp.net asp.net-mvc-3

我的博客中有一个带有局部视图的侧边栏,可让用户注册我的电子邮件新闻源。我想要做的是在发布一些数据后将用户返回到他们来自的页面,并在表单的部分视图中显示任何验证或返回消息。

问题是我的局部视图在新窗口中打开(没有布局)。我如何解决这个问题,以便返回我的博客,并在de sidebar中返回数据?

这是我的观点:

@using Blog.Models.Entities
@model Subscriber

<header>
    <h2>Subscribe</h2>
</header>

<p>Subscribe to my e-mail newsfeed.</p>

@using (Html.BeginForm("Form", "Subscription"))
{
    <div class="editor-label">@Html.LabelFor(subscriber => subscriber.Email)</div>
    <div class="editor-field ">@Html.EditorFor(subscriber => subscriber.Email)</div>

    @Html.ValidationMessageFor(subscriber => subscriber.Email)

    <input type="submit" value="Subscribe" />

    <p>@ViewBag.Result</p>
}

正在处理数据的相关控制器:

public ActionResult Form()
{
    return PartialView("_Form");
}

[HttpPost]
public ActionResult Form(Subscriber subscriber)
{
    if (ModelState.IsValid)
    {
        Subscriber foundSubscriber = _repository.Subscribers.Where(s => s.Email.Equals(subscriber.Email)).FirstOrDefault();
        if (foundSubscriber != null)
        {
            ModelState.AddModelError("Email", "This e-mail address has already been added.");
            return PartialView("_Form", subscriber);
        }

        _repository.SaveSubscriber(subscriber);

        ViewBag.Result = "Succesfully subscribed to the newsletter.";
        return PartialView("_Form");
    }

    ModelState.AddModelError("Email", "Please provide a valid e-mail address.");
    return PartialView("_Form", subscriber);
}

2 个答案:

答案 0 :(得分:1)

提交表单时,浏览器会向服务器发送HTTP Post请求。然后,浏览器显示Response的有效负载。你的帖子控制器动作正在返回一个PartialView,浏览器很乐意呈现它(即使它没有必要的html,head或body标签来使它真正有效的HTML)。

听起来您希望浏览器保留大部分页面加载和呈现,发布表单,然后获取生成的HTML并仅替换加载页面的一部分。简单地说,浏览器不够智能。

你可能想要做的是这样的事情:

  • 用户填写一些表格数据并点击保存/提交/去/无论如何。
  • 但是,您不希望浏览器提交表单,因为它不会以您希望的方式保留当前页面的大部分内容。
  • 相反,您希望“提交”按钮调用一些本地javascript。
  • 本地JS应捆绑用户输入的表单数据,使用该数据制作POST作为有效负载,并使用Ajax提交POST。这将保持当前页面加载,而ajax请求命中您的控制器操作
  • 您的控制器操作保持原样,并返回部分视图。
  • 启动Ajax调用的JS函数还必须定义一个“成功”函数,该函数将在操作完成时被调用。
  • 在该成功函数中,您的javascript将从响应中获取HTML,并使用它来替换保留原始表单的页面区域。

我强烈推荐使用jQuery - 它可以更轻松地制作Ajax请求,处理成功回调,并用结果替换当前加载页面的一部分。我的理解是MS的'unobtrubiveive javascript'也可能有助于实现这一点,但我没有任何直接经验。

显然,所有这些只有在浏览器启用了javascript时才有效。

答案 1 :(得分:1)

我终于找到了问题的解决方案。我用AJAX实现了它,最后得到了以下代码:

_Index.cshtml

<header>
    <h2>Subscribe</h2>
</header>

<p>Subscribe to my e-mail newsfeed.</p>

<div id="subscription-form">
    @{Html.RenderPartial("_Form");}
</div>

_Form.cshtml

@using Blog.Models.Entities
@model Subscriber
@{
    AjaxOptions ajaxOptions = new AjaxOptions
    {
        LoadingElementId = "loading",
        LoadingElementDuration = 2000,
        HttpMethod = "Post",
        UpdateTargetId = "subscription-form"
    };
}

<div id="loading" style="display: none;">
    <p>Processing request...</p>
</div>

@using (Ajax.BeginForm("Index", "Subscription", ajaxOptions))
{
    <div class="editor-label">@Html.LabelFor(subscriber => subscriber.Email)</div>
    <div class="editor-field ">@Html.EditorFor(subscriber => subscriber.Email)</div>

    @Html.ValidationMessageFor(subscriber => subscriber.Email)

    <input type="submit" value="Subscribe" />
}

_Succes.cshtml

@using Blog.Models.Entities
@model Subscriber

<p id="subscription-result">@ViewBag.Result</p>

以下控制器操作方法:

public ActionResult Index()
{
    return PartialView("_Index");
}

[HttpPost]
public PartialViewResult Index(Subscriber subscriber)
{
    if (ModelState.IsValid)
    {
        Subscriber foundSubscriber = _repository.Subscribers.Where(s => s.Email.Equals(subscriber.Email)).FirstOrDefault();
        if (foundSubscriber != null)
        {
            ModelState.AddModelError("Email", "This e-mail address has already been added.");
            return PartialView("_Form", subscriber);
        }

        _repository.SaveSubscriber(subscriber);

        ViewBag.Result = "Succesfully subscribed to the newsletter.";
        return PartialView("_Succes", subscriber);
    }

    ModelState.AddModelError("Email", "Please provide a valid e-mail address.");
    return PartialView("_Form", subscriber);
}

我希望这将有助于任何试图在未来实现同样目标的人。顺便说一下,我在这个博客上找到了解决方案:http://xhalent.wordpress.com/2011/02/05/using-unobtrusive-ajax-forms-in-asp-net-mvc3/