从 Android 连接到 WCF 服务 - 收到 405 - 方法不允许
我创建了一个 WCF 服务,打算在将数据从 Android 应用程序发送到 MSSQL 数据库时使用。
该服务已托管并包含 2 个方法:Data() 和 GetData()。 Data 方法用于将 JSON 发送到,而 GetData 仅返回一个字符串。
我已经尝试过以下操作:
我的数据合同:
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "/Data",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
string Data(Data test);
我的Android代码:
HttpPost request = new HttpPost("http://lino.herter.dk/Service.svc/Data");
try {
JSONObject json = new JSONObject();
json.put("year", 2011);
StringEntity entity = new StringEntity(json.toString());
entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
entity.setContentType( new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
request.setEntity(entity);
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
Log.i("!!! WebInvoke", response.getStatusLine().toString());
if(response!=null) {
InputStream in = response.getEntity().getContent(); //Get the data in the entity'
Log.i("TEST", convertStreamToString(in));
}
类似的方法与GetData一起工作得很好..但是调用Data方法返回:
400 Bad Request
The server encountered an error processing the request. The exception message is 'Object reference not set to an instance of an object.'.
Web.Config看起来像这样:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="WcfEA.Service">
<endpoint address="" behaviorConfiguration="jsonBehavior" binding="webHttpBinding" contract="WcfEA.IService" />
</service>
</services>
</system.serviceModel>
</configuration>
Data方法设置为接收“Data " object:
[DataContract]
public class Data
{
[DataMember(Name = "year")]
public int Year
{
get;
set;
}
}
并且 Data 方法只执行 1 个操作:
return data.year.toString();
I've created a WCF service which I intend to use when sending data from an Android app to a MSSQL database.
The service is already hosted and contains 2 methods.. Data() and GetData(). The Data method is used to POST JSON to and GetData just returns a string.
I've tried the following:
My Data Contract:
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "/Data",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
string Data(Data test);
My Android code:
HttpPost request = new HttpPost("http://lino.herter.dk/Service.svc/Data");
try {
JSONObject json = new JSONObject();
json.put("year", 2011);
StringEntity entity = new StringEntity(json.toString());
entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
entity.setContentType( new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
request.setEntity(entity);
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
Log.i("!!! WebInvoke", response.getStatusLine().toString());
if(response!=null) {
InputStream in = response.getEntity().getContent(); //Get the data in the entity'
Log.i("TEST", convertStreamToString(in));
}
A similar method works just fine with GetData.. but calling the Data method returns:
400 Bad Request
The server encountered an error processing the request. The exception message is 'Object reference not set to an instance of an object.'.
the Web.Config looks like this:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="WcfEA.Service">
<endpoint address="" behaviorConfiguration="jsonBehavior" binding="webHttpBinding" contract="WcfEA.IService" />
</service>
</services>
</system.serviceModel>
</configuration>
The Data method is set to receive a "Data" object:
[DataContract]
public class Data
{
[DataMember(Name = "year")]
public int Year
{
get;
set;
}
}
and the Data method only does 1 operation:
return data.year.toString();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当我过去这样做时,我使用 Fiddler2 来区分我的 .Net 测试应用程序作为请求发送的内容和我的 Android 应用程序发送的内容之间的区别。标头、帖子参数的打包方式等可能存在差异。此外,Fiddler2 还会向您显示响应和响应代码。这应该为您提供解决问题所需的所有信息。
http://www.fiddler2.com/fiddler2/
编辑
发言后在评论中来来回回,这是我认为您的问题的更新答案。
我无法找到用于 Android 客户端和 WCF 服务之间通信的原始 POC 代码,但我确实找到了一些其他发布 json 数据的代码。我所做的与你不同的似乎是我将我的有效负载作为名称/值对传递,因此它在到达服务时被键入。您似乎只传递了 json 数据的原始字符串,因此服务可能期望您的 json 数据作为名称-值对的值,该名称-值对由服务中参数的名称作为键控。
为了解释这两种方法,以下是您使用的将原始字符串数据作为实体传递的方法。
这是我作为 NameValuePair 发布的数据示例。
如果您想传递一个复杂的对象,您可以将其构建为 json 字符串,就像我的示例在上面使用的那样。或者...您可以简单地将“year”作为键,将“2011”作为值传递,这应该是字符串 arg 到达 WCF Web 方法时的值。
When I did this in the past, I used Fiddler2 to tell the difference between what my .Net test application was sending as a request and what my Android app was sending. There may be a discrepancy in the headers, the way your post params are being packaged, etc. Also, Fiddler2 will show you the response and response codes. This should give you all the information you need to figure it out.
http://www.fiddler2.com/fiddler2/
EDIT
After speaking back and forth in the comments, here is an updated answer for what I believe your issue is.
I wasn't able to find the code for the original POC I did for communicating between Android client and WCF service, but I did find some other code where I post json data. What I'm doing differently than you seems to be that I'm passing my payload as a name/value pair so it's keyed when it gets to the service. You seem to be passing just a raw string of json data, so it's possible that the service is expecting your json data as the value of a name-value pair that is keyed by the name of the argument in your service.
To paraphrase the two approaches, here is the method you're using of passing raw string data as the entity.
Here is an example of my data that I'm posting as a NameValuePair
If you want to pass a complex object, you can build it up as a json string as my example makes use of above. OR...you can simply pass "year" as the key and "2011" as the value, and that should be the value of your string arg when it gets to your WCF web method.
之后不应该有换行吗?
另外,除非您确实需要在发送到服务器之前验证 XML,否则建议您只需将实体附加为文本(跳过 xml 内容类型等)并在服务器上解析 XML。
这是因为无论如何您总是都会在服务器上解析和验证传入的数据,否则会带来巨大的安全风险。除非您想通过像这样立即拒绝格式不正确的 XML 来保存请求往返...
另外,您确定您的 XML 是有效的 SOAP 请求 XML 格式吗?由于标头指示消息是 SOAP,因此内容应该是格式正确的 SOAP XML...
Shouldn't there be a line-feed after
<?xml version=\"1.0\"?>
?Also, unless you really need to validate the XML before you send to the server, suggest that you simply attach the entity as text (skip the xml content type etc.) and parse the XML on the server.
That is because you always would be parsing and validating in-coming data on the server anyway, otherwise it opens up huge security risks. Unless you want to save a request round-trip by rejecting improperly-formatted XML off-hand like this...
Also, are you sure your XML is in valid SOAP request XML format? Since your header indicates the message to be SOAP, the content should be properly-formatted SOAP XML...
你能从你的c# WCF 发布你的web.config 吗?有时我创建了一个充当 WebService 的 WCF 服务器,我也遇到了同样的问题,这全都与配置有关。除了 actuakl 配置之外,如果您默认使用 wsHttpBinding 托管 WCF 服务,它将启用“Windows”身份验证。您如何创建服务?
Could you post your web.config from you c# WCF? Some time I created a WCF server which acts as WebService and I had the same problems and it was all about the configuration. Apart from the actuakl configuration if you are hosting a a WCF service using a wsHttpBinding by default it will enbale 'Windows' autentification. How are you creating the service?