5

我正在尝试使用 ASP.NET 页面来测试 Web 服务调用,该页面创建了一个包含用户名和密码字段以及“提交”按钮的表单。(我使用的 jQuery 和 .js 文件都包含在 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 对不同的服务器进行 Web 服务调用,发送 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;
}

但是,由于我调用的 Web 服务与 ASP.NET、C# 和 JavaScript 文件位于不同的服务器上,因此我没有收到statusText警报responseText

不知何故,没有任何东西被发送到网络服务,我也没有得到任何回报,甚至没有错误。我尝试在属性中放置一个函数beforeSend,但没有触发。我需要一种特殊的方式来处理调用服务器外 Web 服务吗?

更新!

在 jjnguy、Janie 和 Nathan 的建议下,我现在正在尝试使用 HttpWebRequest 对 Web 服务进行服务器端调用。使用 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 协议。除了让 ASP.NET 页面 URL 以 HTTPS 开头(不是一个选项)之外,我还能做些什么来解决这个问题?

4

4 回答 4

3

原来我在更新中发布的代码是正确的,我只是有一个错字并且数据字符串中的一个设置不正确。

    string data = "{\"Header\":{\"AuthToken\":null,\"ProductID\":\"NOR\",\"SessToken\":null,\"Version\":1},\"ReturnAuthentication\":true,\"Password\":\"" + pwd + "\",\"Username\":\"" + uname + "\",\"ReturnCredentials\":true}";
于 2009-07-24T20:50:02.630 回答
2

为简单起见,为什么不在服务器端用 C# 编写对 Web 服务的调用呢?

在 C# 中发送请求和获取响应的能力与使用 Javascript 相同。

这是您在 C# 中的函数的破解:

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

免责声明这未经测试。

于 2009-07-23T21:11:15.363 回答
1

而不是使用客户端脚本从服务器发出请求;使用服务器端代码发出请求

编辑以扩大答案:

从 Visual Studio 中的 Web 项目中,单击添加 Web 引用,然后指向您最初通过客户端脚本访问的服务:(我相信它是' https://myHost.com/V1/Identity/Authenticate

您现在可以使用 c# 代码而不是 js 与服务对话(并传入用户提供的凭据。)

此外,由于对服务的请求来自服务器,而不是浏览器;您绕过适用的跨域限制。

进一步编辑以显示其他技术:

如果您不喜欢使用 Visual Studio 为您生成服务代理的想法,那么您可以使用 WebClient 或 HttpRequest 自己手工制作请求

WebClient: 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

于 2009-07-23T21:12:22.740 回答
0

好像您遇到了相同的来源政策

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

我相信有办法规避它,但我认为其他海报是正确的。在服务器上,编写使用 HttpWebRequest 调用 Web 服务的方法,然后使用 JavaScriptSerializer 解析出 JSON。我花了大部分下午的时间研究这个,因为我必须自己写一些类似的东西。

>>>>  Nathan

PS 我更喜欢@Janie 的计划......你能用一个返回 JSON 的 Web 服务以及一个返回 XML 的 Web 服务来做到这一点吗?

于 2009-07-23T21:32:49.467 回答