使用多个参数调用 WCF RESTful 服务方法时出现 InvalidOperationException?

InvalidOperationException when calling a WCF RESTful service method with multiple arguments?

我有以下代码用于名为 AuthenticationService 的服务:

IAuthenticationService.cs

[ServiceContract]
public interface IAuthenticationService
{
    [OperationContract]
    [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    bool Login(string username, string password, string applicationName);
}

AuthenticationService.svc.cs

public sealed class AuthenticationService : IAuthenticationService
{
    public bool Login(string username, string password, string applicationName)
    {
        // TODO: add the logic to authenticate the user

        return true;
    }
}

Web.config

<system.serviceModel>
    <!-- START: to return JSON -->
    <services>
        <service name="ImageReviewPoc.Service.AuthenticationService">
            <endpoint contract="ImageReviewPoc.Service.Contracts.IAuthenticationService" binding="webHttpBinding" behaviorConfiguration="jsonBehavior"/>
        </service>
    </services>
    <!-- END: to return JSON -->
    <behaviors>
        <!-- START: to return JSON -->
        <endpointBehaviors>
            <behavior name="jsonBehavior">
                <webHttp/>
            </behavior>
        </endpointBehaviors>
        <!-- END: to return JSON -->
        <serviceBehaviors>
            <behavior>
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add scheme="http" binding="webHttpBinding"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>

并且我有以下使用该服务的控制台应用程序:

Program.cs

internal class Program
{
    private static void Main(string[] args)
    {
        Login().Wait();
    }

    private static async Task Login()
    {
        var client = new AuthenticationServiceClient();
        var ok = await client.LoginAsync("User", "Password!", "Console Application");
        client.Close();

        Console.WriteLine(ok);
    }
}

App.config

<system.serviceModel>
    <client>
        <endpoint address="http://localhost:62085/AuthenticationService.svc/"
         binding="webHttpBinding"
         contract="AuthenticationServiceReference.IAuthenticationService"
         kind="webHttpEndpoint" />
    </client>
</system.serviceModel>

我使用 Postman 来测试发送以下 JSON 数据的服务并且它有效:

{"username": "reviewer", "password": "456", "applicationName": "123"}

但是,当我使用控制台应用程序测试服务时,我得到了

System.InvalidOperationException: Operation 'Login' of contract 'IAuthenticationService' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped.

IAuthenticationService.cs代码可以看出,我已经将BodyStyle设置为Wrapped。有人可以指导我这里做错了什么吗?

注意以下几点:

这是您调用服务的方式。

    public void DoLogin()
    {
        string uri = "http://localhost:62085/AuthenticationService.svc/Login";
        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);

        request.Method = "POST";
        request.ContentType = "text/json";

        string data = "{\"username\": \"reviewer\", \"password\": \"456\", \"applicationName\": \"123\"}";

        System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
        byte[] bytes = encoding.GetBytes(data);

        request.ContentLength = bytes.Length;

        using (Stream requestStream = request.GetRequestStream())
        {
            // Send the data.
            requestStream.Write(bytes, 0, bytes.Length);
        }

        using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(x))
        {
            using(var responseStream = response.GetResponseStream())
            {
                using(var reader = new StreamReader(responseStream))
                {
                    //Here you will get response
                    string loginResponse = reader.ReadToEnd();
                }

            }
        }
    }

添加到 Login/LoginAsync 客户端合同方法

 [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]. 

因此您的客户合同将如下所示:

    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.IAuthenticationService")]
public interface IAuthenticationService {

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAuthenticationService/Login", ReplyAction="http://tempuri.org/IAuthenticationService/LoginResponse")]
    [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    bool Login(string username, string password, string applicationName);

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IAuthenticationService/Login", ReplyAction="http://tempuri.org/IAuthenticationService/LoginResponse")]
    [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    System.Threading.Tasks.Task<bool> LoginAsync(string username, string password, string applicationName);
}

客户合同自动生成。因此,您应该在每次更新服务参考后执行此操作。 enter link description here