我想创建一个IIS托管的Web服务,我将使用通用Windows存储aoo(windows phone / windows 8.1 / windows RT)来使用它。
据我所知,通用应用程序不支持使用“添加服务引用”的代理类生成和SOAP调用,因此我需要创建一个RESTful Web服务并在通用应用程序中手动使用它。
我在整个网络中尝试过几十种教程和方法,但我从未设法将数据实际发布到网络服务。
我需要将在共享库中定义的自定义类的对象发送到Web服务。我知道我需要序列化Object并将其包含在POST请求中,但无论我尝试什么,我最终会遇到不同的问题 - 例如HTTP 400错误请求:传入消息具有意外的消息格式'Raw ”。该操作的预期消息格式是'Xml'; '的Json'。
我已经看到了几种手动设置内容类型标头的方法,但我找到的方法在通用应用程序中不可用。
有人可以提供适合我的方案的信息或示例(通过通用应用程序发布)吗?
更新1:有关进一步说明:我知道WCF如何工作,我已经能够完成this post中描述的基本GET请求。但是,我无法将其扩展为也可以使用POST请求。
我试过的一些代码:
public async static void SendStartup(CustomClass customObject)
{
var httpClient = new HttpClient();
var serialized = JsonConvert.SerializeObject(customObject);
var response = await httpClient.PostAsync("http://localhost:49452/Metrics.svc/LogStartup", new StringContent(serialized));
string content = await response.Content.ReadAsStringAsync();
}
Web服务接口:
[OperationContract]
[WebInvoke(UriTemplate = "LogStartup", Method="POST", BodyStyle=WebMessageBodyStyle.Wrapped)]
string LogStartup(CustomClass obj);
实现:
public void LogStartup(CustomClass obj)
{
// nothing
}
这例如在运行时因上述错误而失效
答案 0 :(得分:6)
您的代码存在两个问题。
1)您在提出请求时必须发送Content-Type
标题
var content = new StringContent(serialized,Encoding.UTF8,"application/json");
2)您必须使用BodyStyle = WebMessageBodyStyle.Bare
WebMessageBodyStyle.Bare
可以在您的示例中使用一个参数,但如果您想发布更多参数,那么您必须使用WebMessageBodyStyle.Wrapped
但是,您发布的对象应该修改为
var serialized = JsonConvert.SerializeObject(new { obj = customObject });
以下是可以使用自托管WCF服务进行测试的工作代码
async void TestRestService()
{
var ready = new TaskCompletionSource<object>();
Task.Factory.StartNew(() =>
{
var uri = new Uri("http://0.0.0.0:49452/Metrics.svc/");
var type = typeof(Metrics);
WebServiceHost host = new WebServiceHost(type, uri);
host.Open();
ready.SetResult(null);
},TaskCreationOptions.LongRunning);
await ready.Task;
var customObject = new CustomClass() { Name = "John", Id = 333 };
var serialized = JsonConvert.SerializeObject(new { obj = customObject });
var httpClient = new HttpClient();
var request = new StringContent(serialized,Encoding.UTF8,"application/json");
var response = await httpClient.PostAsync("http://localhost:49452/Metrics.svc/LogStartup", request);
string content = await response.Content.ReadAsStringAsync();
}
[ServiceContract]
public class Metrics
{
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped)]
public string LogStartup(CustomClass obj)
{
return obj.Name + "=>" + obj.Id;
}
}
public class CustomClass
{
public string Name { set; get; }
public int Id { set; get; }
}
PS:如果你想返回一个json响应,那么你可以使用ResponseFormat=WebMessageFormat.Json
。然后,您应该将WebInvoke
属性更改为
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped,ResponseFormat=WebMessageFormat.Json)]
BTW:您仍然可以通过设置AutomaticFormatSelectionEnabled
来动态选择返回的内容类型(xml或json)。
答案 1 :(得分:2)
How to use HttpClient to post JSON data
基本上您似乎需要向StringContent()
构造函数添加更多参数,如下所示:
new StringContent(serialized, System.Text.Encoding.UTF8, "application/json");
答案 2 :(得分:1)
您需要了解的有关 Windows Communication Foundation 的一件事是 ABC的。
所以这个理论非常简单,虽然在你编码的时候,却很奇怪。可以找到一个简单的教程here或here。在Code Project中可以找到其他几个教程来实现这种精确的方法。
了解多态性可能有助于理解 Windows Communication Foundation ,因为它非常依赖它。
[ServiceContract]
public interface IContent
{
[OperationContract]
void DoSomething(SomeModel model);
}
所以你在这里做的是定义你的服务,定义你的方法。正如我上面提到的,我们明确地声明了我们的合同,但我们还没有实现我们的方法。我们还打算通过SomeModel
这将是我们的数据合同。
我们将建立我们的模型:
[DataContract]
public class SomeModel
{
[DataMember]
public string Name { get; set; }
}
模型可以像上面那样非常简单,或者非常复杂。这取决于使用情况。
现在我们想实现我们的方法:
public class Content : IContent
{
public void DoSomething(SomeModel model)
{
// Implementation
}
}
现在在客户端上,您只需使用您的服务。一旦理解了基础知识以及它如何序列化和反序列化,就可以将它用于REST。还有哪些教程。