MVC - 为什么Ajax对Controller Action参数的调用始终为null?

时间:2014-06-26 04:17:13

标签: jquery asp.net-mvc asp.net-mvc-4 razor

我正在使用.get对Controller Action进行Ajax调用,但是当Controller Action触发时,该参数始终为null。触发器是.on(change)中包含的jQuery脚本中的_Layout.cshtml事件。我之前发布了这个问题,但线程被无关的喋喋不休破坏了。有人可以帮我解决为什么会这样吗?这是代码:

部分视图:〜/ Views / Shared / _LanguageListPartial.cshtml

@Html.DropDownListFor(
    x => x.SelectedLanguage,
    Model.Languages,
    new { @class = "form-control" }
)

_Layout.cshtml

<form action="/Account/ListPartial" method="post"
    class="navbar-form navbar-right nopadding" role="" style="margin: 8px 0;">
    @{Html.RenderAction("LanguageListPartial", "Account");} 
</form>

<div id="test"></div>

GET:/ Account / LanguageListPartial

[AllowAnonymous]
[ChildActionOnly]
public ActionResult LanguageListPartial()
{
    // Retrieve user's language preference. Default = en-US
    string SelectedLanguage = GetLanguage();

    var model = new LanguageListPartialViewModel();

    model.Languages = GetLanguageList();
    model.SelectedLanguage = SelectedLanguage;

    return PartialView("_LanguageListPartial", model);
}

获取:/ Account / TestPartial(针对.on(更改)事件的测试操作)

[AllowAnonymous]
public ActionResult TestPartial(string SelectedLanguage)
{
    // Set Language selection in cookie and user profile
    SetLanguage("SelectedLanguage");

    var model = new LanguageListPartialViewModel();

    // Create List<SelectedItemList> of Languages
    model.Languages = GetLanguageList();

    // Set user's Language preference for dropdown
    model.SelectedLanguage = SelectedLanguage;

    return View(model);
}

我无法完全调试上述代码,但下拉列表按预期呈现:

<form method="post" action="/Account/ListPartial">
    <select name="SelectedLanguage" id="SelectedLanguage">
        <option value="en-US">English</option>
        <option value="fr-CA">Francais</option>
        <option value="pt-BR">Portugues</option>
        <option value="es-MX">Espanol</option>
    </select>
</form>

<div id="test"></div>

在_Layout.cshtml的底部我有这个jQuery:

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryUI")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)

<script type="text/javascript">
    $(document).ready(function () {
        $(function () {
            $('#SelectedLanguage').on('change', function () {
                var a = $(this).val();
                $('#test').load("/Account/TestPartial/" + a);
                return false;
            });
        });
    });
</script>

</body>
</html>

问题是$(this).val()== null无论我尝试什么。我没有看到任何这些代码有任何问题,并希望比我的眼睛更清晰可能会看到错误。我尝试过IE,Firefox和Chrome。所有都给出了相同的结果。我已经尝试将块移动到PartialView中,但是Controller Action甚至没有被解雇。

我是否因为放置jQuery而违反了一些结构规则?我在各种页面中都有其他jQuery脚本,它们都可以工作,尽管这是我在布局中尝试过的唯一一个。

另一个非常奇怪的事情是,由于某种原因,这个脚本不会出现在Firefox中进行调试。我以前没有想过我曾遇到过这个问题,但它根本没有出现在Scripts下面。虽然,它确实被执行了,因为当我在下拉列表中进行更改时,正在调用Controller Action。

编辑#1

在Fiddler中查看,我发现jQuery实际上正在运行:

GET http://localhost:59655/Account/TestPartial/pt-BR HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: text/html, */*; q=0.01
Referer: http://localhost:59655/Account/Login?ReturnUrl=%2F
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko
Host: localhost:59655
DNT: 1
Connection: Keep-Alive
Cookie: __RequestVerificationToken=8mK4-p6MrZCx6Iw6dvdad70QvjenwUbW6S0uxxpW7LxkAWn7wzLXompOz59o9Oq2GEt2A7sHvYZXKMOOJqnXGuCshKyHQsNFCJ62rhf2YIA1

即使将pt-BR传递给Controller Action TestPartial,SelectedLanguage也为空。

所以在这一点上我觉得_Layout.cshtml编码是正确的(包括jQuery)。部分视图代码工作并呈现良好的HTML。问题在于TestPartial(),但我不知道它为什么会出错。 :S

编辑#2

我找到了一个与ASP.NET MVC有同样问题的人interesting article。他指出,当Controller Action参数的名称与模型成员之一相同时,就会发生此问题。我的参数被命名为与相关模型属性相同,但重命名它没有区别。这篇文章告诉我,为什么会发生这种情况可能会有一些非常模糊的原因。

编辑#3

根据@Rune的建议,我更改了参数id,现在它是TestPartial(string id)。由于jQuery脚本调用id仍为null,因此没有任何区别。我有其他控制器操作,除了id之外还有不同的参数名称,它们可以正常工作。当我按照@Rune的建议配置路由时,我收到一条错误消息,指出无法找到TestPartial.cshtml并显示已检查的所有位置。

2 个答案:

答案 0 :(得分:1)

您需要配置路线以捕获所选语言。像

这样的东西
routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{selectedLanguage}",
                defaults: new { controller = "Home", action = "Index", selectedLanguage = "en-US" }
            );

中心问题是:你必须以某种方式告诉ASP.NET MVC你希望你的URL的最后一部分与selectedLanguage参数相关联 - MVC怎么能猜到它拥有?

或者,如果您有默认路线设置

routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

您必须更改操作才能使用id参数

ActionResult TestPartial(string id) { }

答案 1 :(得分:0)

我喜欢这样做我的脚本标签 - 您也可以在on事件处理程序的主体中尝试console.log(),以确保正确选择所有元素。

<script type = "text/javascript" >
    function($){
       $(document).ready(function(){

       });
    })(jQuery);
</script>