Вызов веб-сервиса на внешнем сервере из javascript с использованием asp.net и С#

Я пытаюсь протестировать вызовы веб-службы, используя страницу ASP.NET, которая создает форму с полями имени пользователя и пароля и кнопкой «Отправить». (И jQuery, и файл .js, которые я использую, включены в теги script в элементе head.)

Кнопка «Отправить» вызывает функцию, созданную в файле кода C#, которая вызывает отдельный файл JavaScript.

protected void mSubmit_Click(object sender, EventArgs eventArgs)
{
    String authenticate = String.Format("Authentication(\"{0}\",\"{1}\");", this.mUsername.Text,this.mPassword.Text);
    Page.ClientScript.RegisterStartupScript(this.GetType(), "ClientScript", authenticate, true);
}

Функция JavaScript, Authenticate, делает вызов веб-службы, используя jQuery и Ajax, на другой сервер, отправляя параметры JSON и ожидая ответа JSON.

function Authentication(uname, pwd) {

    //gets search parameters and puts them in json format
    var params = '{"Header":{"AuthToken":null,"ProductID":"NOR","SessToken":null,"Version":1},"ReturnAuthentication":true,"Password":"' + pwd + '","Username":"' + uname + '",”ReturnCredentials”:false }';

    var xmlhttp = $.ajax({
        async: false,
        type: "POST",
        url: 'https://myHost.com/V1/Identity/Authenticate',
        data: params,
        contentType: 'application/json'
    });

    alert(xmlhttp.statusText);
    alert(xmlhttp.responseText);

    return;
}

Однако, поскольку веб-служба, которую я вызываю, находится на сервере, отличном от сервера ASP.NET, C# и JavaScript, я не получаю предупреждение statusText или responseText.

Почему-то ничего не отправляется в веб-службу, и я ничего не получаю обратно, даже ошибки. Я попытался поместить функцию в атрибут beforeSend, но это не сработало. Есть ли какой-то особый способ обращения с внешним веб-сервисом?

ОБНОВЛЕНИЕ!

По совету jjnguy, Джени и Натана я сейчас пытаюсь вызвать веб-службу на стороне сервера, используя HttpWebRequest. Используя часть кода jjnguy, а также код из этот вопрос, я придумал это.

public static void Authenticate(string pwd, string uname)
{
    string ret = null;

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://myhost.com/V1/Identity/Authenticate");
    request.ContentType = "application/json";
    request.Method = "POST";

    string data = "{\"Header\":{\"AuthToken\":null,\"ProductID\":\"NOR\",\"SessToken\":null,\"Version\":1},\"ReturnAuthentication\":true,\"Password\":\"" + pwd + "\",\"Username\":\"" + uname + "\",\"ReturnCredentials\":false }'";

    byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);
    request.ContentLength = byteData.Length;

    using (Stream postStream = request.GetRequestStream()) 
    {
        postStream.Write(byteData, 0, byteData.Length);
    }

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    using (response)
    {
        // Get the response stream  
        StreamReader reader = new StreamReader(response.GetResponseStream());

        // Console application output  
        ret = reader.ReadToEnd();
    }

    Console.WriteLine(ret);
}

Однако я получаю сообщение об ошибке (400) Bad Request с удаленного сервера, когда пытаюсь получить ответ от моего HttpWebRequest. Значение свойства Response исключения равно {System.Net.HttpWebResponse}, а значение свойства Status равно ProtocolError. Я почти уверен, что это потому, что URL-адрес использует протокол HTTP SSL. Что я могу сделать, чтобы обойти это, кроме того, что URL-адрес страницы ASP.NET начинается с HTTPS (не вариант)?


person elemjay19    schedule 23.07.2009    source источник
comment
Это решение в стиле Руба Голдберга, вам нужно сильно упростить.   -  person Janie    schedule 24.07.2009
comment
Согласованный. Я рад, что мы на одной волне.   -  person jjnguy    schedule 24.07.2009
comment
Можно ли увидеть сервис из браузера?   -  person Janie    schedule 24.07.2009
comment
Я не уверен, что вы имеете в виду.   -  person elemjay19    schedule 24.07.2009


Ответы (4)


Оказывается, код, который я разместил в своем обновлении, был правильным, у меня просто была опечатка и одна неверная настройка в строке данных.

    string data = "{\"Header\":{\"AuthToken\":null,\"ProductID\":\"NOR\",\"SessToken\":null,\"Version\":1},\"ReturnAuthentication\":true,\"Password\":\"" + pwd + "\",\"Username\":\"" + uname + "\",\"ReturnCredentials\":true}";
person elemjay19    schedule 24.07.2009

Для простоты, почему бы вам не написать вызов веб-сервиса на C# на стороне сервера?

У вас есть те же возможности для отправки запросов и получения ответов в C#, что и в Javascript.

Вот трещина в вашей функции на С#:

public static string Authenticate(string pwd, string uname)
{
    HttpWebRequest requestFile = (HttpWebRequest)WebRequest.Create("https://myHost.com/V1/Identity/Authenticate");
    requestFile.ContentType = "application/json";
    requestFile.Method = "POST";
    StreamWriter postBody = new StreamWriter(requestFile.GetRequestStream())
    using (postBody) {
        postBody.Write("{\"Header\":{\"AuthToken\":null,\"ProductID\":\"NOR\",\"SessToken\":null,\"Version\":1},\"ReturnAuthentication\":true,\"Password\":\"" + pwd + "\",\"Username\":\"" + uname + "\",\"ReturnCredentials\":false }'");
    }
    HttpWebResponse serverResponse = (HttpWebResponse)requestFile.GetResponse();
    if (HttpStatusCode.OK != serverResponse.StatusCode)
        throw new Exception("Url request failed.  Connection to the server inturrupted");
    StreamReader responseStream = new StreamReader(serverResponse.GetResponseStream());
    string ret = null;
    using (responseStream) {
        ret = responseStream.ReadLine();
    }
    return ret;
}

Отказ от ответственности Это не тестировалось.

person jjnguy    schedule 23.07.2009
comment
Надеюсь, вы поместите туда несколько блоков использования. У меня осталось два голоса - не заставляйте меня использовать один против вас... - person John Saunders; 24.07.2009
comment
p.s. Пожалуйста, никогда не копируйте и не вставляйте код, который я публикую на этом сайте, в свой собственный производственный код. Бог убьет котят! - person jjnguy; 24.07.2009

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

РЕДАКТИРОВАТЬ, чтобы расширить ответ:

В своем веб-проекте в Visual Studio нажмите «Добавить веб-ссылку» и укажите на службу, к которой вы изначально обращались через свой клиентский скрипт: (Я полагаю, что это было «https://myHost.com/V1/Identity/Authenticate)

Теперь вы можете общаться со службой, используя код C# вместо js (и передавать предоставленные пользователями учетные данные).

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

ДАЛЬНЕЙШЕЕ РЕДАКТИРОВАНИЕ, чтобы показать дополнительную технику:

Если вам не нравится идея использования Visual Studio для создания прокси-сервера службы, вы можете самостоятельно создать запрос с помощью WebClient или HttpRequest.

Веб-клиент: http://msdn.microsoft.com/en-us/library/system.net.webclient(VS.80).aspx

HttpWebRequest: http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest(VS.80).aspx

person Janie    schedule 23.07.2009
comment
У меня нет доступа к этому сервису в моем веб-проекте. Он находится в другой части кодовой базы, чем мои файлы. - person elemjay19; 24.07.2009
comment
Я это понимаю; VS создаст прокси-объект, который будет взаимодействовать с этой службой от вашего имени. У вас будет доступ ко всем методам на нем... - person Janie; 24.07.2009

Похоже, вы используете ту же политику происхождения

http://en.wikipedia.org/wiki/Same_origin_policy

Я считаю, что есть способы обойти это, но я думаю, что другие плакаты правы. На сервере напишите методы, которые используют HttpWebRequest для вызова веб-службы, а затем используйте JavaScriptSerializer для анализа JSON. Я провел большую часть дня, исследуя это, потому что мне придется написать что-то подобное самому.

>>>>  Nathan

P.S. Мне больше нравится план @Janie ... Можете ли вы сделать это с веб-службой, которая возвращает JSON, а также с той, которая возвращает XML?

person Nathan    schedule 23.07.2009
comment
Вы не добавили JavaScriptSerializer. /jk Мне все еще любопытно, можете ли вы создавать прокси-классы для служб JSON... Не могу заставить его работать на моей машине здесь... - person Nathan; 24.07.2009