ASP.NET MVC Ajax.BeginForm不起作用

时间:2010-09-05 17:39:58

标签: asp.net-mvc

<script src="../../Scripts/MicrosoftAjax.debug.js" type="text/javascript"></script>

<script type="text/javascript">
    function loginOK()
    {
        var item = document.getElementById('statusLabel');
        item.innerHTML = "OK";
        document.getElementById('LoadImg').style.visibility = 'hidden';
    }

    function process()
    {
        var lab = document.getElementById('statusLabel');
        lab.innerHTML = 'Checking...';
        lab.style.color = 'Black';
        document.getElementById('LoadImg').style.visibility = 'visible';
    }

    function fail()
    {
        var lab = document.getElementById('statusLabel');
        lab.innerHTML = 'Login is being used';
        lab.style.color = 'Red';
        document.getElementById('LoadImg').style.visibility = 'hidden';
    }
</script>

 <div style="width:30%; float:left;">
     <label for="Login">Login:</label>
     <%= Html.TextBoxFor(model=>model.Login) %>
     <%= Html.ValidationMessageFor(model=>model.Login) %>

     <img id="LoadImg" alt="" src="../../Content/Images/ajax-loader.gif" style="visibility:hidden;"/>
     <br />
     <label id="statusLabel" />
     <br />
     <%=Ajax.ActionLink("CheckLogin","CheckLoginAvailability", "Account",
        new AjaxOptions { UpdateTargetId = "statusLabel", OnBegin = "process", OnFailure = "fail", OnSuccess="loginOK"})%>
 </div>

,在AccountController中:

    [AcceptVerbs(HttpVerbs.Post)]
    public void CheckLoginAvailability(string login)
    {
        //do some job
    }

并且,FireBug说没有找到/ Account / CheckLoginAvailability。此外,在回调后隐藏了ActionLink。为什么?

2 个答案:

答案 0 :(得分:3)

您在谈论问题中的Ajax.BeginForm,但在您提供的标记中无处可见。我可以在您的代码中看到几个问题:

  1. 您的操作方法不会返回ActionResult。是的,我知道,你会说这是可能的,对,但这是违反任何良好做法,惯例和让你的控制器单元测试友好。
  2. 你正在使用混合标记和javascript的Microsoft Ajax,其中恕我直言的原因有多种:增加带宽当然会导致性能下降,无法将javascript外部化为单独的文件以便通过客户端浏览器缓存它们,不得不写下document.getElementByIdinnerHTMLstyle.colorstyle.visibility等内容......这些内容无法保证跨浏览器正常工作。
  3. 我建议你改进这个。虽然这不能回答您的问题,但请将其作为替代方法。

    与往常一样,首先要处理的是定义一个模型,在您的情况下可能看起来像这样:

    public class LoginViewModel
    {
        public string Login { get; set; }
    }
    

    当然您可能希望添加其他字段,例如Password,但这暂时不在范围内。下一步是编写一个处理这个模型的控制器(同时你应该已经为未来的控制器设置单元测试以准备地面):

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            // Simply return the Login form
            return View(new LoginViewModel());
        }
    
        [HttpPost]
        public ActionResult Index(LoginViewModel model)
        {
            // Deal with the actual authentication, etc...
            throw new NotImplementedException();
        }
    
        [HttpPost]
        public ActionResult CheckLoginAvailability(LoginViewModel model)
        {
            // TODO: query your datasource to determine whether 
            // model.Login is taken
            // For this purpose we will suppose that it is taken
            bool isLoginTaken = true;
    
            // return a JSON object containing the result
            return Json(new { IsLoginTaken = isLoginTaken });
        }
    }
    

    最后一部分是绘制屏幕:

    <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<SomeNs.Models.LoginViewModel>" %>
    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Login</title>
        <!-- Use a separate CSS to avoid mixing markup with styling -->
        <link rel="stylesheet" type="text/css" href="<%: Url.Content("~/content/site.css") %>" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
        <!-- Always use HTML helpers when dealing with Urls -->
        <script type="text/javascript" src="<%: Url.Content("~/scripts/login.js") %>"></script>
    </head>
    <body>
        <% using (Html.BeginForm()) { %>
            <%: Html.LabelFor(x => x.Login) %>:
            <%: Html.TextBoxFor(x => x.Login) %>
            <%: Html.ValidationMessageFor(x => x.Login) %>
            <br/>
            <!-- Always use HTML helpers when dealing with Urls -->
            <img id="loadImg" alt="" src="<%: Url.Content("~/content/images/ajax-loader.gif") %>" style="display:none;" />
            <br />
            <div id="statusLabel"></div>
            <br />
            <!-- Give this link an id so that we can easily identify it from javascript -->
            <%: Html.ActionLink("CheckLogin", "CheckLoginAvailability", "Home", null, new { id = "checkLogin" })%>
            <input type="submit" value="Login" />
        <% } %>
    </body>
    </html>
    

    最后一部分是在login.js文件中不引人注意地附加我们的javascript(当然使用jQuery):

    // When the DOM is ready
    $(function () {
        // Attach a click handler to the checkLogin link
        $('a#checkLogin').click(function () {
            // When this link is clicked send an AJAX POST request
            // to the address this link is pointing to
            $.ajax({
                type: 'POST',
                url: this.href,
                // Pass as parameter in the POST body the login
                // entered by the user
                data: { login: $('#Login').val() },
                beforeSend: function () {
                    // show the spinner image before sending any AJAX request
                    // to inform the user of an ongoing activity
                    $('#loadImg').show();
                },
                complete: function () {
                    // hide the spinner image when the AJAX request completes
                    // no matter if it succeeded or not
                    $('#loadImg').hide();
                },
                success: function (result) {
                    // if the AJAX request succeeds
                    // query the IsLoginTaken property
                    // of the resulting JSON object
                    if (result.IsLoginTaken) {
                        // Show the status label with red if the login is taken
                        $('#statusLabel').html('Login is being used').css('color', 'red');
    
                    } else {
                        // Show the status label in black if the login is not taken
                        $('#statusLabel').html('OK').css('color', 'black');
                    }
                }
            });
            return false;
        });
    });
    

答案 1 :(得分:1)

正如@SLaks所说,操作可以返回void,但我认为操作签名是这样的,它需要返回一个操作结果,如果你不想返回任何内容,你可以返回EmptyResult。 p>

请参阅此http://www.asp.net/mvc/tutorials/asp-net-mvc-controller-overview-cs

尝试将AccountController更改为

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CheckLoginAvailability(string login)
{
   //do some job
   return new EmptyResult();
}