使用WCF和通用应用程序创建/使用REST WebService

lee*_*rog 2 c# rest wcf web-services windows-store-apps

我想创建一个IIS托管的Web服务,我将使用通用Windows存储aoo(windows phone/windows 8.1/windows RT)来使用它.

据我所知,通用应用程序不支持使用"添加服务引用"的代理类生成和SOAP调用,因此我需要创建一个RESTful Web服务并在通用应用程序中手动使用它.

我已经在整个网络中尝试过几十个教程和方法,但我从未设法将数据实际发布到网络服务.

我需要将在共享库中定义的自定义类的对象发送到Web服务.我知道我需要序列化Object并将其包含在POST请求中,但无论我尝试什么,我最终都会遇到不同的问题 - 例如HTTP 400错误请求:传入的消息具有意外的消息格式'Raw'.该操作的预期消息格式是'Xml'; 'Json的'.

我已经看到了几种手动设置内容类型标头的方法,但是我找到的方法在通用应用程序中不可用.

有人可以提供适合我的场景的信息或示例(通过通用应用程序发布)吗?

更新1:为了进一步澄清:我知道WCF是如何工作的,我已经能够完成像在描述一个基本的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();
}
Run Code Online (Sandbox Code Playgroud)

Web服务接口:

[OperationContract]
[WebInvoke(UriTemplate = "LogStartup", Method="POST", BodyStyle=WebMessageBodyStyle.Wrapped)]
string LogStartup(CustomClass obj);
Run Code Online (Sandbox Code Playgroud)

执行:

public void LogStartup(CustomClass obj)
{
    // nothing
}
Run Code Online (Sandbox Code Playgroud)

例如,这会在运行时因上述错误而失效

L.B*_*L.B 6

您的代码有两个问题.

1)Content-Type在提出请求时必须发送标题

var content = new StringContent(serialized,Encoding.UTF8,"application/json");
Run Code Online (Sandbox Code Playgroud)

2)你必须使用BodyStyle = WebMessageBodyStyle.Bare

WebMessageBodyStyle.Bare可以使用一个参数,如您的示例,但如果您想发布更多参数,那么您必须使用WebMessageBodyStyle.Wrapped但是,您发布的对象应该被修改为

var serialized = JsonConvert.SerializeObject(new { obj = customObject });
Run Code Online (Sandbox Code Playgroud)

这是一个可以使用自托管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; }
}
Run Code Online (Sandbox Code Playgroud)

PS:如果你想返回一个json响应,那么你可以使用ResponseFormat=WebMessageFormat.Json.然后,您应该将WebInvoke属性更改为

[WebInvoke(Method = "POST",  BodyStyle = WebMessageBodyStyle.Wrapped,ResponseFormat=WebMessageFormat.Json)]
Run Code Online (Sandbox Code Playgroud)

顺便说一句:您仍然可以通过设置动态选择返回的内容类型(xml或json)AutomaticFormatSelectionEnabled.