簡體   English   中英

在調用帶有多個參數的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:合同'IAuthenticationService'的操作'Login'指定了要序列化的多個請求正文參數,而沒有任何包裝器元素。 沒有包裝器元素,最多可以序列化一個body參數。 刪除多余的正文參數,或將WebGetAttribute / WebInvokeAttribute上的BodyStyle屬性設置為Wrapped。

IAuthenticationService.cs代碼中可以看到,我已經將BodyStyle設置為Wrapped 有人可以指導我這里做錯了什么嗎?

請注意以下幾點:

  • 我已經在Stackoverflow和Internet上搜索了解決方案。 幾乎所有解決方案都與設置BodyStyle 它可能對其他人有所幫助,但對我卻沒有做太多。
  • 我嘗試了LoginLoginAsync ; 結果是一樣的
  • 我通過在Visual Studio 2013(最終版,如果您想知道)中通過“添加服務引用”將其添加來引用該服務
  • 我知道我可以使用其他方式致電服務。 例如HttpClient,但我想知道的是為什么自動生成的客戶端不起作用

這就是您應該如何致電您的服務。

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

            }
        }
    }

添加到登錄/登錄異步客戶端合同方法

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

客戶合同是自動生成的。 因此,您應該在每次更新服務引用之后執行此操作。 在此處輸入鏈接說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM