![](/img/trans.png)
[英]Fail to Post to WCF Rest Service over HTTPS 400 bad request
[英]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.