Проблема маршрутизации URL с вызовом Javascript (Jquery) к контроллеру MVC3 / Action / ID, возвращающему 404, должна получить JSon - PullRequest
1 голос
/ 05 марта 2012

Вопрос: Как мне кодировать URL, передаваемый в javascript, чтобы в собранной / развернутой версии код шел в контроллер / действие с идентификатором и возвращал данные JSon, как это работает в среда Visual Studio?

Цель: вернуть даты в средство выбора даты, поскольку они будут отключены. Я ожидаю возврата массива строк JSon, представляющих собой даты, которые затем передаются в средство выбора даты.

Соответствие другим: Возврат данных JSon из вызова Controller / Action / ID кажется обычным делом. Я вижу другие вопросы, касающиеся вопросов маршрутизации, а также JSon, и jQuery, похоже, является популярным способом улучшения веб-разработки.

Справка: У меня есть средство выбора даты jQuery-UI, которое вызывает Controller / Action / ID и возвращает данные json в средство выбора даты. Он отлично работает при работе в Visual Studio, но не работает при сборке и развертывании в среде Dev. Код передает URL, который генерируется и передается в jQuery: / Secure / Validation / getDisabledDates / 999

Мы используем Umbraco с каталогом / Secure в области Umbraco для хранения нашего кода MVC. URL, который пытается создать код, затем генерирует в среде Dev: / Безопасность / проверки / getDisabledDates / 999 Если я смотрю вызов и ошибки в Firebug, я вижу, что ошибка для следующего: POST http://dev.ourcompanyname.com/Secure/Validation/getDisabledDates/999 302 Найдено (если я продолжу расследование, я обнаружу, что это действительно 404, который был отправлен на страницу с ошибкой, и вот что было найдено.)

Я использую @ Url.Action в представлении, чтобы получить правильный (надеюсь) URL-адрес действия, но когда в среде Dev выполняется запрос javascript, возвращается значение 404. Код попадает в javascript код и отображает URL в оповещении, которое выглядит прямо на моих глазах. Код, похоже, не доходит до контроллера MVC (я попытался поместить туда сообщение).

Кажется, это потому, что контроллер на самом деле не является отдельной реальной страницей в каталоге, потому что код MVC скомпилирован в DLL. Я слышал это, и это имеет смысл, но другие люди в мире, кажется, называют диспетчерами, поэтому я не уверен, в чем моя проблема здесь.

Изначально был только один набор дат, поэтому некоторые вызовы кода говорят только о GetDates, но затем он был разбит на Widget, поэтому вызовы отражают ByWidget, поэтому ID передается. Все вызовы отслеживаются правильно, и код работает в Dev.

SetDates, которая вызывается при успехе в функции javascript, - это еще одна функция javascript, но я поместил оповещения в SetDates, в среде Dev код не зашел так далеко, предположительно, потому что он не найдет код в ValidationController.

Буду очень признателен за любые полезные предложения!

Технические характеристики: MVC3, Javascript 1.6.4, JQuery JQuery-UI-1.8.17, IIS 7.5, Умбрако 4.7.1, Visual Studio 2010

Код Javascript в отдельном файле .js:

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

Код MVC в ValidationController:

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

}

Что я сделал, чтобы попытаться решить эту проблему перед публикацией:

Ответы [ 2 ]

0 голосов
/ 29 августа 2012

Хотя я согласен со многими ответами Элая, я не согласен с его отклонением Url.Action и других URL, генерирующих помощников MVC. Суть в том, что они подключены к механизму маршрутизации MVC, поэтому, если маршрут меняется, и вы используете помощников URL, вы должны в ноль обновлять URL в своих представлениях. Но если вы жестко запрограммировали все URL-адреса вместо использования Url.Action, вам придется вернуться назад и вручную изменить каждый URL-адрес.

Вот отличная статья от Фила Хаака с примером того, как Url.Action спасло МНОГО головных болей при работе с ошибкой в ​​MVC: http://haacked.com/archive/2011/02/20/routing-regression-with-two-consecutive-optional-url-parameters.aspx

0 голосов
/ 05 марта 2012

Я никогда не позволяю 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);
}
...