Ошибка неверного запроса на POST для WCF Веб-служба Restful, размещенная в IIS с использованием обычной аутентификации через https - PullRequest
2 голосов
/ 06 марта 2012

У меня есть отдыхающий веб-сервис wcf 3.5, размещенный в IIS 7.5.Это настройка для использования базовой аутентификации через https.Я добавил как можно больше информации ниже (названия классов и т. Д. Были немного изменены).Будем благодарны за любые советы или предложения.

Каждый раз, когда я пытаюсь отправить POST либо через Fiddler, либо через клиентское приложение, я получаю это сообщение:

HTTP / 1.1 400 Bad Request

Я включил журналы svctrace, которые дают мне эту информацию:

System.Runtime.Serialization.SerializationException, mscorlib, Версия = 2.0.0.0, Культура = нейтральная, PublicKeyToken = b77a5c561934e089

Невозможнодесериализовать тело XML с корневым именем 'user-search-request' и корневым пространством имен '' (для операции 'FetchMatchingUsers' и контракта ('IMyService', 'http://tempuri.org/')) с использованием DataContractSerializer. Убедитесь, что тип, соответствующий 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;
    }
}

1 Ответ

0 голосов
/ 07 апреля 2012

Здравствуйте, вы можете попробовать [XmlSerializerFormat] в соответствии с вашим контрактом на обслуживание, поэтому он должен выглядеть следующим образом:

[ServiceContract]
[XmlSerializerFormat]
interface IMyService

Второе, что вы можете сделать, это добавить обертку к вашему POST следующим образом:

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

В противном случае виноват ваш конфигурационный файл, если я рискну предположить, он должен быть настроен с помощью webHttpBinding.

...