Почему один и тот же точный код вылетает в одном приложении и работает в другом?

Я пытаюсь вызвать метод Rest API Web в приложении из клиентского приложения. У меня есть два клиентских приложения - с одним оно работает, с другим - нет.

Код для вызова метода REST идентичен. Это точно такой же точный код сервера, конечно.

В сбойном клиентском приложении оно терпит неудачу в этой строке:

var webResponse = (HttpWebResponse)webRequest.GetResponse();

... и код в обоих приложениях абсолютно одинаков до момента отказа, за исключением того, что отказавший находится в обработчике событий, а рабочий - нет. Ну, еще одно (связанное) отличие, кроме того, что тестовый код находится в обработчике событий, а "реальный" код находится в отдельном методе, заключается в том, что отдельный метод также находится в отдельном классе. Почему это будет иметь значение, я не знаю, но я вроде как хватаюсь за соломинку здесь. Вот:

Cursor.Current = Cursors.WaitCursor;
try
{
    // Cannot start with String.Empty or " "; they both fail for some reason - Controller method is not even called.
    string lastIDFetched = "0";
    const int RECORDS_TO_FETCH = 100;
    bool moreRecordsExist = true;

    try
    {
        while (moreRecordsExist)
        {
            string formatargready_uri = string.Format("http://localhost:28642/api/InventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH);
            var webRequest = (HttpWebRequest)WebRequest.Create(formatargready_uri); 
            // GET is the default method/verb, but it's here for clarity
            webRequest.Method = "GET";
            var webResponse = (HttpWebResponse)webRequest.GetResponse();// <-- this throws an exception when there is no longer any data left

Определение неверного метода:

private void buttonGetInvItemsInBlocks_Click(object sender, EventArgs e)

Определение метода работы:

public static List<HHSUtils.InventoryItem> GetBatchOfInventoryItems()

На той, которая не работает, F10 в последней строке идет прямо к блоку исключений (goto считается вредным - без шуток!), Но исключение мне ничего не показывает - зависание над этой строкой:

catch (Exception ex)

... я вижу только " Exception | System.Exception base {object} | object "

Оба клиента встроены в Visual Studio 2008 и предназначены для.NET 3.5; сервер VS 2013, .NET 4.5.1

Вот подсказка, я полагаю: в сбойном коде целевое устройство установлено на "Устройство Windows CE" (оно развертывается на портативное устройство, которым я управляю через "Удаленное управление дисплеем для Windows CE")

Кто-нибудь здесь связывается с их внутренним Коломбо?

ОБНОВИТЬ

Я изменил код из этого:

var webResponse = (HttpWebResponse)webRequest.GetResponse();

...к этому:

using (var webResponse = (HttpWebResponse)webRequest.GetResponse())

... и это не имеет значения - он все равно переходит прямо из этой строки в блок catch без полезных данных в отображаемом исключении.

В моем тестовом приложении я изменил код, чтобы использовать "более лучший" способ (с помощью); это работает в любом случае, тогда как другое приложение не работает ни в коем случае. IOW: использование use - это хорошо, но в этом случае нет никакой разницы.

ОБНОВЛЕНИЕ 2

В ответ на ответ JayC я попробовал все следующие "строки подключения" - все с одинаковым результатом:

string uri = string.Format("http://localhost:28642/api/InventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH); // Fails on "using" line below with no usable exception data
//string uri = string.Format("http://192.112.263.38:28642/api/InventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH); <-- same failure
//string uri = string.Format("http://192.112.263.38/api/InventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH); <-- same failure
//string uri = string.Format("http://192.112.263.38:80/api/InventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH); <-- same failure
//string uri = string.Format("http://192.112.263.38:777/api/InventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH); <-- same failure
//string uri = string.Format("http://192.112.263.38:28642/api/inventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH); <-- same failure
//string uri = string.Format("http://192.112.263.38/api/inventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH); <-- same failure
//string uri = string.Format("http://192.112.263.38:80/api/inventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH); <-- same failure
//string uri = string.Format("http://192.112.263.38:777/api/inventoryItems/{0}/{1}", lastIDFetched, RECORDS_TO_FETCH); <-- same failure

ОБНОВЛЕНИЕ 3

В ответ на комментарий Романа Грубера о CAS: в Википедии есть страница для устранения неоднозначности для CAS ( http://en.wikipedia.org/wiki/Cas_(disambiguation)), но ни одна из предложенных возможностей не представляется разумной для этого контекста.

Основная статья, OTOH, содержит несколько аббревиатур CAS в разделе Computing. На что вы ссылаетесь:

Central Authentication Service, a single sign-on protocol
Channel Associated Signaling, a type of communication signaling
Code Access Security in the Microsoft .NET framework

?

ОБНОВЛЕНИЕ 4

Хорошо, я добавил код, предложенный парой кошек:

catch (WebException webex)
{
    HttpWebResponse hwr = (HttpWebResponse) webex.Response;
    HttpStatusCode hsc = hwr.StatusCode;
    MessageBox.Show(string.Format("{0} Status code == {1}", webex.Message, hsc.ToString()));
}

... и вот что я вижу, когда точка останова достигает улова:

введите описание изображения здесь

И вот сообщение об ошибке показано:

"Удаленный сервер возвратил ошибку: (400) Bad Request. Код состояния == Bad Request"

Я думаю, что проблема в "строке подключения"; как видно из обновления 2, я перепробовал все, что только мог придумать, и ничего не работает, чтобы подключить устройство к рабочему столу.

5 ответов

Решение

Неудачное приложение развертывается на переносном устройстве, и все же URI установлен на localhost??

Возможно, вы захотите использовать имя хоста, которое соответствует фактическому компьютеру, на котором размещена служба.

Редактировать: я ничего не знаю об устройствах Windows CE, но кажется, что должны быть более простые способы получения более явной информации об исключениях от устройства, которое развернуто на устройстве. Я подозреваю, что это ваша главная проблема, которую нужно решить, если случится так, что ваша непосредственная проблема будет решена с помощью того, что я упомянул выше. Я надеюсь, что это что-то тривиальное, как debug="True" это можно было бы установить в файле app.config, но мне пришлось бы это исследовать.

Вы пытались запустить приложение на устройстве CE без отладчика? Просто любопытно, происходит ли сбой только в среде отладки или нет.

Также Роман Грубер задал хороший вопрос, а я не увидел ответа:

Вы можете видеть устройство с вашего компьютера, но может ли устройство видеть сеть? Откройте веб-браузер на устройстве и попробуйте получить доступ к любой странице в сети, чтобы проверить...

Просто длинный выстрел: есть ли разница в потоках между обоими приложениями? Если я правильно понимаю, сбойное приложение вызывает сетевой код из основного потока (из обработчика событий кнопки). Android может вызвать сбой вашего приложения, если вы сделаете это (чтобы основной поток не блокировался). Но я не знаю, имеет ли Windows CE подобную систему...

Я попробую это как ответ, чтобы уточнить мои заметки по вопросам:

1.: CAS = Code Access Security - извините, я предположил, что аббревиатура достаточно распространена в среде.NET.

2.: Аутентифицировать запрос на сервере:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Credentials = new NetworkCredential("username", "password");

Но: я просто понял кое-что еще... предыдущие ответы и / или вопросы немного вводят меня в заблуждение, и полоса прокрутки в вашем примере кода тоже не помогла. Это метод "WebRequest.Create", который вызывает исключение?? Это еще не доступ к любой сети вообще. Это не может быть ни имя хоста / IP-адрес, ни какие-либо учетные данные, связанные в этом случае. Это все еще может быть связано с CAS. Но, скорее всего, это неправильный URI...

Попробуйте добавить

MessageBox.Show(formatargready_uri);

перед вызовом WebRequest. Создайте и посмотрите URL-адрес вашего приложения на устройстве. URI-разбор тоже может быть "легковесным". Далее, я бы порекомендовал также использовать окно сообщения внутри блока catch:

catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

3.: Подключение к рекламной сети: все, что вы указываете, это то, что вы можете видеть устройство с вашего ПК, но может ли устройство видеть сеть? Откройте веб-браузер на устройстве и попробуйте получить доступ к любой странице в сети, чтобы проверить...

Мне пришлось добавить это в C: \ Users \ clay \ Documents \ IISExpress \ config \ applicationhost.config:

<binding protocol="http" bindingInformation="*:28642:shannon2" />

... и использовать эту "строку подключения" в моем коде:

http://shannon2:28642/api/InventoryItems

Теперь я могу подключиться; Я думаю, что я был очень близок (так близко, и все же так далеко) раньше, но это должна была быть именно такая комбинация, чтобы работать.

Другие вопросы по тегам