Javascript(Jquery)调用MVC3 Controller/Action/ID的URL路由问题,返回404,

URL Routing issue with Javascript (Jquery) call to MVC3 Controller/Action/ID, returning 404, should get JSon

本文关键字:URL 路由 问题 返回 ID Action Jquery 调用 Controller MVC3 Javascript      更新时间:2023-09-26

问题:如何对传递给javascript的URL进行编码,以便在构建/部署的版本中,代码将转到带有id的控制器/操作并返回JSon数据,就像在Visual Studio环境中一样?

目标:将日期返回到日期选择器,因为这些日期将被禁用。我期望返回JSon字符串数组,这些字符串是日期,然后输入到日期选择器中。

与他人的相关性:从对Controller/Action/ID的调用中返回JSon数据似乎是一件常见的事情。我看到了其他关于路由问题的问题,以及JSon,jQuery似乎是增强web开发的一种流行方式。

背景:我有一个jQueryUI日期选择器,它调用Controller/Action/ID并向日期选择器返回json数据。它在VisualStudio中运行时运行良好,但在构建和部署到Dev环境时失败。代码将生成并传递给jQuery的URL传递为:/安全/验证/getDisabledDates/999

我们正在使用Umbraco,在Umbraco区域中有一个名为/Secure的目录来保存我们的MVC代码。代码尝试然后在开发环境中生成的URL是:/安全/验证/getDisabledDates/999如果我观察Firebug中的调用和错误,我会看到以下错误:岗位http://dev.ourcompanyname.com/Secure/Validation/getDisabledDates/999302找到了(如果我进一步调查,我发现它真的是一个404,被发送到错误页面,这就是找到的。)

我在视图中使用@Url.Action来获得操作的正确Url(希望如此),但当在Dev环境中发出javascript请求时,返回的是404。代码进入javascript代码,并在警报中显示URL,这在我看来是正确的。代码似乎没有MVC控制器那么远(我试着在那里放了一个消息框)。

这似乎是因为控制器实际上不是目录中一个不同的、真实的页面,因为MVC代码被编译到DLL中。我听说过,这很有道理,但世界上其他人似乎在呼叫控制器,所以我不确定我的问题是什么。

最初只有一组日期,所以一些代码调用只说GetDates,但后来它被Widget分解了,所以调用会反映ByWidget,所以会传递一个ID。所有调用都能正确跟踪,代码在Dev.中运行

在javascript函数中成功调用的SetDates是另一个javascript函数,但我在SetDates中设置了警报,在Dev环境中,代码没有走那么远,可能是因为它在ValidationController中找不到代码。

如果有任何有用的建议,我们将不胜感激!

规格:MVC3,Javascript 1.6.4,Jquery Jquery-ui-1.8.17,IIS 7.5,Umbraco 4.7.1,Visual Studio 2010

单独.js文件中的Javascript代码:

function getDisabledDatesByWidget(urlGetDisabledDatesByWidget) {
    alert('urlGetDisabledDatesByWidget = ' + urlGetDisabledDatesByWidget);
    $.ajax({
        //data: {id: id},
        type: "POST",
        async: false,
        url: urlGetDisabledDatesByWidget,
        dataType: 'json',
        success: setDates,
        constrainInput: true,
        defaultDate: new Date(defaultCutoff + " 00:00")
    });
}

视图中的MVC代码,在文档准备功能中:

    widgetId = '@ViewBag.WidgetId';
    var urlGetDisabledDatesByWidget = '@Url.Action("getDisabledDates", "Validation", new{id = @ViewBag.WidgetId})';
    getDisabledDatesByWidget(urlGetDisabledDatesByWidget);

ValidationController中的MVC代码:

[HttpPost]
public JsonResult getDisabledDates(int id)
{
    List<String> disabledDateStrings = new List<String>();
    List<DateTime> _DisabledDateDates = DisabledDateSetup.GetDisabledDateDatesByWidget(id).Value.ToList();
    ////Convert disabled dates to string array
    foreach (DateTime disabledDate in _DisabledDateDates)
    {
        disabledDateStrings.Add(disabledDate.ToString("M-d-yyyy"));
    }
    ChangeType _changeType = ChangeType.NoChangeType;
    ChangeDateRangeSetupResponse _dates = DisabledDateSetup.GetValidChangeDateRange(_changeType);
    return Json(new
    {
        disabledDates = disabledDateStrings,
        startDate = UnixTicks(_dates.Value.BeginDate),
        endDate = UnixTicks(_dates.Value.EndDate)
    });
}

视图中的MVC代码,在div中:

 @Html.TextBoxFor(model => model.SetupDate, new { id = "DisabledDateCalendar"})

全局asax路由:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Account", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );
}

在发布之前,我尝试解决了这个问题:

  • 在我的办公室咨询了其他开发商
  • 使用Firefox/Firebug和Chrome/Chrome的F12功能在Dev中跟踪调用
  • 在代码中放置警报/消息框,部署它,并查看显示的内容和未显示的内容
  • 在谷歌上搜索答案
  • 审查了许多堆栈溢出问题,包括:
  • asp.net MVC路由-javascript url 404错误
  • 在外部JavaScript中处理ASP.NET MVC路由
  • 使用default.aspx/controller/action样式url时ASP.NET MVC路由失败

我从不让Razor将数据注入我的JavaScript,只在语义上注入HTML。此外,与其使用Url.Action和那些奇怪的助手,不如手动呈现URL和标记?MVC似乎添加了很多不必要的方法,而且更容易理解事情的实际进展:

代替:

@Html.TextBoxFor(model => model.SetupDate, new { id = "DisabledDateCalendar"})

怎么样:

<input type="text" id="DisabledDateCalendar" value="@Model.SetupDate" />

使您的其他代码从JavaScript:语义上可访问

<input type="hidden" id="widgetId" value="@ViewBag.WidgetId" />
<input type="hidden" id="urlGetDisabledDatesByWidget" value="/secure/validation/getdisableddates/@ViewBag.WidgetId" />

另外,您的AJAX是同步的原因是什么?让我们实现异步,现在您不需要将Razor与JS:混合在一起

function getDisabledDatesByWidget(urlGetDisabledDatesByWidget) {
    var urlGetDisabledDatesByWidget = $('#urlGetDisabledDatesByWidget').val(),
        widgetId = $('#widgetId').val();
    alert('urlGetDisabledDatesByWidget = ' + urlGetDisabledDatesByWidget);
    $.ajax({
        //data: {id: id},
        type: "post",
        url: urlGetDisabledDatesByWidget,
        dataType: 'json',
        constrainInput: true,
        defaultDate: new Date(defaultCutoff + " 00:00")
    })
    .done(setDates);
}

虽然我同意Eli的很多回答,但我不同意他驳回Url.Action和其他生成Url的MVC助手。对他们来说,关键是他们被MVC的路由引擎钩住了,所以如果路由发生了变化,而你正在使用URL助手,你就必须对视图中的URL进行零更新。但是,如果你已经对所有Url进行了硬编码,而不是使用Url.Action,你将不得不返回并手动更改每个Url。

以下是Phil Haack的一篇优秀文章,其中举例说明了Url.Action在解决MVC中的一个错误时如何避免了很多麻烦:http://haacked.com/archive/2011/02/20/routing-regression-with-two-consecutive-optional-url-parameters.aspx