简体   繁体   English

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

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

Question: How do I code the URL passed to javascript so that in the built/deployed version the code will go to the controller/action with the id and return the JSon data, like it works in the Visual Studio environment? 问题:我该如何编码传递给javascript的URL,以便在生成/部署的版本中,该代码将转到具有ID的控制器/操作并返回JSon数据,就像它在Visual Studio环境中一样?

Goal: to return dates to the datepicker, because they will be disabled dates. 目标:将日期返回到日期选择器,因为它们将被禁用。 I expect a return of JSon array of strings that are dates that are then fed into the datepicker. 我希望返回的是字符串的JSon数组,然后将这些日期输入到datepicker中。

Relevance to others: Returning JSon data from a call to Controller/Action/ID seems like it would be a common thing to do. 与其他人的相关性:从调用Controller / Action / ID返回JSon数据似乎很常见。 I see other questions regarding routing issues, as well as JSon, and jQuery seems to be a popular way to enhance web development. 我看到了有关路由问题以及JSon的其他问题,而jQuery似乎是增强Web开发的一种流行方法。

Background: I have a jQuery-UI datepicker that calls a Controller/Action/ID and returns json data to the datepicker. 背景:我有一个jQuery-UI datepicker,它调用Controller / Action / ID并将json数据返回给datepicker。 It works perfectly when running within Visual Studio, but fails when built and deployed to the Dev environment. 在Visual Studio中运行时,它可以完美运行,但在构建和部署到Dev环境中时,它会失败。 The code passes the URL that is generated and passed to the jQuery is: /Secure/Validation/getDisabledDates/999 该代码将生成并传递给jQuery的URL传递为:/ Secure / Validation / getDisabledDates / 999

We are using Umbraco, with a directory called /Secure within the Umbraco area to hold our MVC code. 我们正在使用Umbraco,在Umbraco区域中有一个名为/ Secure的目录来保存我们的MVC代码。 The URL that the code tries then generates on the Dev environment is: /Secure/Validation/getDisabledDates/999 If I watch the call and the errors in Firebug, I see that an error for the following: POST http://dev.ourcompanyname.com/Secure/Validation/getDisabledDates/999 302 Found (if I investigate further, I find it was really a 404, that got sent to the error page, and that's what was found.) 然后,代码尝试在Dev环境上生成的URL是:/ Secure / Validation / getDisabledDates / 999如果我观看了该呼叫以及Firebug中的错误,则看到以下错误:POST http://dev.ourcompanyname .com / Secure / Validation / getDisabledDates / 999 302找到(如果我进一步调查,发现它确实是404,并被发送到错误页面,这就是发现的内容。)

I'm using @Url.Action in the view to get the correct (hopefully) URL to the action, but when the javascript request is made in the Dev environment, the return is a 404. The code gets into the javascript code and displays the URL in an alert, which looks right to my eyes. 我在视图中使用@ Url.Action来获取操作的正确(希望)URL,但是当在Dev环境中发出javascript请求时,返回值为404。该代码进入javascript代码并显示警报中的网址,它对我来说似乎是正确的。 The code does not seem to get as far as the MVC controller (I tried putting a messagebox there). 该代码似乎没有达到MVC控制器的程度(我尝试在其中放置一个消息框)。

This seems to be because the controller isn't actually a distinct, real page within a directory, because the MVC code is compiled into a DLL. 这似乎是因为控制器实际上不是目录中的不同的真实页面,因为MVC代码已编译为DLL。 I've heard this and it makes sense, but other people in the world seem to be calling controllers, so I'm not sure what my problem is here. 我已经听说过这一点,并且很有意义,但是世界上其他人似乎都在打电话给控制器,所以我不确定我的问题在哪里。

Originally there was only one set of dates, so some code calls only say GetDates, but then it was broken up by Widget, so calls then reflect ByWidget, so an ID is passed. 最初只有一组日期,所以一些代码调用只说了GetDates,但是后来它被Widget分解,因此调用随后反映了ByWidget,因此传递了一个ID。 All of the calls trace correctly, and the code works in Dev. 所有调用均正确跟踪,并且代码可在Dev中工作。

SetDates that gets called on success in the javascript function is another javascript function, but I have put alerts in SetDates, in the Dev environment the code does not get that far, presumably because it will not find the code in the ValidationController. 在javascript函数中成功调用的SetDates是另一个javascript函数,但是我在SetDates中放置了警报,在Dev环境中,代码无法实现那么远,大概是因为它无法在ValidationController中找到代码。

Any helpful suggestions would be very greatly appreciated! 任何有用的建议将不胜感激!

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

Javascript code in separate .js file: 单独的.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 code in the view, in the document ready function: 视图中的MVC代码,在文档准备功能中:

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

MVC code in ValidationController: 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 code in the view, in the div: 视图中的div中的MVC代码:

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

Global asax routing: 全局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
    );

}

What I've done to try to resolve this before posting: 在发布之前,我已尝试解决此问题:

While I agree with a lot of Eli's answer, I do not agree with his dismissal of Url.Action and the other URL generating MVC helpers. 尽管我同意Eli的许多回答,但我不同意他对Url.Action和其他生成MVC帮助器的URL的解雇。 The point to them is that they're hooked into the routing engine of MVC, so if a route changes and you're using the URL helpers, you have to do zero updating of URLs in your views. 指向它们的关键是它们已连接到MVC的路由引擎中,因此,如果路由发生更改并且您正在使用URL帮助器,则必须对视图中的URL进行零更新。 But if you've hard-coded all the URLs instead of using Url.Action, you'll have to go back and manually change each URL. 但是,如果您对所有URL进行了硬编码而不是使用Url.Action,则必须返回并手动更改每个URL。

Here's an excellent article from Phil Haack with an example of how Url.Action saved a LOT of headaches when working around a bug in MVC: http://haacked.com/archive/2011/02/20/routing-regression-with-two-consecutive-optional-url-parameters.aspx 这是Phil Haack的精彩文章,其中举例说明了在解决MVC中的错误时Url.Action如何避免很多麻烦: http : //haacked.com/archive/2011/02/20/routing-regression-with-两个连续的可选URL参数.aspx

I never let Razor inject data into my JavaScript, only semantically into HTML. 我从不让Razor将数据注入到我的JavaScript中,仅从语义上将其注入HTML。 Also, instead of using Url.Action and those weird helpers, how about just rendering the URL and markup manually? 此外, Url.Action使用Url.Action和那些怪异的助手, Url.Action手动呈现URL和标记呢? MVC seems to add a lot of needless methods, plus it's easier to read where things are actually going: MVC似乎添加了许多不必要的方法,而且更容易理解实际情况:

Instead of: 代替:

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

How about: 怎么样:

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

Make your other code semantically accessible from JavaScript: 使其他代码可从JavaScript语义访问:

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

Also, is there a reason your AJAX is synchronous? 另外,您的AJAX是否同步是有原因的吗? Let's make that async, and now you don't have Razor mixed in with your JS: 让我们保持异步,现在您无需在JS中混入Razor:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM