簡體   English   中英

POST到WCF上的錯誤請求錯誤Wrestful Web服務托管在IIS上,使用基於HTTP的基本身份驗證

[英]Bad Request error on POST to WCF Restful web service Hosted in IIS using Basic Authentication over https

我有一個IIS 7.5托管的WCF 3.5 Restful Web服務。 設置為通過https使用基本身份驗證。 我在下面添加了盡可能多的信息(類的名稱等已稍作更改)。 任何意見或建議,不勝感激。

每當我嘗試通過Fiddler或通過客戶端應用程序發送POST時,都會收到以下消息:

HTTP / 1.1 400錯誤請求

我打開了svctrace日志,為我提供了以下信息:

System.Runtime.Serialization.SerializationException,mscorlib,Version = 2.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089

無法使用DataContractSerializer反序列化具有根名稱'user-search-request'和根名稱空間'(對於操作'FetchMatchingUsers'和合同('IMyService','http://tempuri.org/')的XML主體)。 確保將與XML對應的類型添加到服務的已知類型集合中。

該服務的URL如下所示: https : //mysite.com/program/user/v1.0/MyService.svc

我的服務合同如下所示:

[ServiceContract]
interface IMyService
{       
    [WebInvoke(UriTemplate = "",
               Method = "POST",
               RequestFormat = WebMessageFormat.Xml,
               ResponseFormat = WebMessageFormat.Xml)]
    [OperationContract]
    Users FetchMatchingUsers(User u);
}

我的服務實現如下所示:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService
{
    static Users _users = new Users();
    public Users FetchMatchingUsers(User u)
    {
              return SearchByFullName(u.FirstName, u.LastName);


    }
}

DataContract看起來像這樣:

[CollectionDataContract(Name = "user-search-request", Namespace = "")]
public class Users : List<User>
{ }

[DataContract(Name = "user", Namespace = "")]
public class User
{

    [DataMember(Name = "first-name")]
    public string FirstName { get; set; }

    [DataMember(Name = "last-name")]
    public string LastName { get; set; }
 }

服務模型的設置如下:

    <system.serviceModel>
<diagnostics>
  <messageLogging logMalformedMessages="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
</serviceHostingEnvironment>

<services>
  <service behaviorConfiguration="basic" name="MyService">
    <clear />
    <endpoint address="/program/user/v1.0" binding="basicHttpBinding"
      name="Default" contract="MyService.IMyService"
      listenUriMode="Explicit">
      <identity>
        <certificateReference storeName="My" storeLocation="LocalMachine"
          x509FindType="FindBySubjectDistinguishedName" />
      </identity>
    </endpoint> 
    <host>
      <baseAddresses>
        <add baseAddress="https://mysite.com" />
      </baseAddresses>
    </host>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="basic">
      <serviceMetadata httpsGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
<bindings>
  <basicHttpBinding>
    <binding name="basicHttpBinding">
      <readerQuotas maxStringContentLength="10500" />
      <security mode="Transport">
        <transport clientCredentialType="Basic" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

我的POST設置如下:

    private void DoPost

    {  
        String firstname = "Test";
        String lastname = "User";
        User user = new User();
        user.FirstName = firstname;
        user.LastName = lastname;


        String uristring = @"https://mysite.com/program/user/v1.0/MyService.svc/";

        Uri uri = new Uri(uristring);

        HttpWebRequest client = (WebRequest.Create(uri)) as HttpWebRequest;

        NetworkCredential cred = new NetworkCredential(_username, _password, _domain);
        String username = cred.Domain + "\\" + cred.UserName;
        byte[] credentialBuffer = new UTF8Encoding().GetBytes(username + ":" + cred.Password);

        client.Credentials = cred;
        client.Method = "POST";
        client.ContentType = "application/xml";
        client.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);


        List<User> users = new List<User>();
        users.Add(user);

 SerializeUsers sa = new SerializeUsers();
        String output = sa.SerializeUsers(users);


        client.ContentLength = output.Length;

        // Write the request StreamWriter 
        StreamWriter requestWriter = new StreamWriter(client.GetRequestStream(), System.Text.Encoding.ASCII);
        requestWriter.Write(output.ToString());
        requestWriter.Close();
        // Do the request to get the response 
        try
        {
            StreamReader responseReader = new StreamReader(client.GetResponse().GetResponseStream());
            String response = responseReader.ReadToEnd();
            responseReader.Close();
        }
        catch (WebException ex)
        {
            String message = ex.Message;
        }


    }

我現在的反序列化器只是一個測試,因此xml實際上是硬編碼的,但是一旦解決了這個問題,我確實需要使其正確工作。

    public class SerializeUsers
{
    public String SerializeUsers(List<User> ts)
    {
        String xml = @"<user-search-request xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">";
        foreach (User t in ts)
        {
            xml += @"<user>";

            xml += @"<first-name>" + t.FirstName + "</first-name>";
            xml += @"<last-name>" + t.LastName + "</last-name></user>";



        }

        xml += @"</user-search-request>";


        return xml;
    }
}

您好,您可以在服務合同下嘗試使用[XmlSerializerFormat] ,因此它應如下所示:

[ServiceContract]
[XmlSerializerFormat]
interface IMyService

您可能想做的第二件事是像在POST中那樣添加一個包裝器:

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

如果我不敢猜測,那么您的配置文件將失敗,應該使用webHttpBinding進行設置。

暫無
暫無

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

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