Ошибка известного типа WCF

#wcf #known-types

#wcf #известные типы

Вопрос:

Я получаю эту ошибку при вызове моей службы:

 Server Error in '/' Application.
--------------------------------------------------------------------------------

Configuration Error 
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately. 

Parser Error Message: There was an error while trying to serialize parameter http://DSD.myCompany.net/DsdWebServices/2011/05/:config. The InnerException message was 'Type 'System.OrdinalComparer' with data contract name 'OrdinalComparer:http://schemas.datacontract.org/2004/07/System' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.  Please see InnerException for more details.

Source Error: 


Line 130:            passwordAttemptWindow="10"
Line 131:            passwordStrengthRegularExpression=""
Line 132:            type="DsdWebsite.Providers.DsdMembershipProvider, DsdWebsite.Providers" />
Line 133:      </providers>
Line 134:    </membership>


Source File: C:DevelopmentDSD WebsiteWebUIweb.config    Line: 132 


--------------------------------------------------------------------------------
Version Information: Microsoft .NET Framework Version:2.0.50727.5444; ASP.NET Version:2.0.50727.5420 
  

Служба является службой передачи данных для поставщика членства. Я создал DTO MembershipUser для перемещения данных взад и вперед по службе. Он использует только стандартные классы: string, int, DateTime. Я использую Guid вместо object для ProviderUserKey.

Интерфейс для службы выглядит следующим образом:

 [ServiceContract(Namespace = "http://DSD.myCompany.net/DsdWebServices/2011/05/")]
[ServiceKnownType(typeof(MembershipUserDTO))]
[ServiceKnownType(typeof(NameValueCollection))]
[ServiceKnownType(typeof(Guid))]
[ServiceKnownType(typeof(DateTime))]
public interface IDsdMembershipProviderService
{
    [OperationContract]
    void Initialize(string name, NameValueCollection config);

    [OperationContract]
    MembershipUserDTO CreateUser(string username, 
        string salt,
        string encodedPassword,
    ...
  

DTO выглядит следующим образом

 namespace DsdWebsite.Services.Providers
{
    [Serializable]
    [DataContract]
    [KnownType(typeof(Guid))]
    [KnownType(typeof(DateTime))]
    public class MembershipUserDTO
    {
        public MembershipUserDTO(string providerName, string userName, Guid providerUserKey, string email,
                              string passwordQuestion, string comment, bool isApproved, bool isLockedOut,
                              DateTime creationDate, DateTime lastLoginDate, DateTime lastActivityDate,
                              DateTime lastPasswordChangedDate, DateTime lastLockoutDate,
                              string firstName, string lastName, string cellPhone, string officePhone,
                              string brokerId, bool isAdmin, bool mustChangePassword)
        {
            ProviderName= providerName;
            UserName = userName;
            ProviderUserKey= providerUserKey;
            Email= email;
            PasswordQuestion= passwordQuestion;
            Comment= comment;
            IsApproved=isApproved;
            IsLockedOut= isLockedOut;
            CreationDate= creationDate;
            LastLoginDate= lastLoginDate;
            LastActivityDate= lastActivityDate;
            LastPasswordChangedDate = lastPasswordChangedDate;
            LastLockoutDate=lastLockoutDate;
...
  

Наконец, мой web.config выглядит следующим образом:

 <membership
 defaultProvider="DsdMembershipProvider"
 userIsOnlineTimeWindow="15"
 hashAlgorithmType="">   <providers>
     <clear/>
     <add
         name="DsdMembershipProvider"
         connectionStringName="DsdMembershipConnectionString"
         enablePasswordRetrieval="true"
         enablePasswordReset="true"
         requiresQuestionAndAnswer="true"
         applicationName="/DsdWebsite/"
         requiresUniqueEmail="true"
         passwordFormat="Encrypted"
         maxInvalidPasswordAttempts="5"
         minRequiredPasswordLength="7"
         minRequiredNonalphanumericCharacters="0"
         passwordAttemptWindow="10"
         passwordStrengthRegularExpression=""
         type="DsdWebsite.Providers.DsdMembershipProvider,
 DsdWebsite.Providers" />  
 </providers> </membership>
  

Как я могу определить, какой тип или объект вызывает ошибку?
Спасибо

Комментарии:

1. Я не могу найти систему. OrdinalComparer — откуда это берется?

2. @Terry: Я вскоре обновлю ответ информацией.

3. Общее предположение: щелкните правой кнопкой мыши ссылку на службу, выберите Настроить ссылку на службу, поиграйте с раскрывающимися списками «тип коллекции» и «Тип коллекции словаря».

Ответ №1:

Используйте следующий ServiceKnownTypeAttribute конструктор, чтобы указать тип класса ( declaringType ), содержащего статический метод methodName , который будет возвращать службы известных типов:

 public ServiceKnownTypeAttribute(
    string methodName,
    Type declaringType
)
  

Внутри вышеупомянутого статического метода добавьте все известные типы сервисов, которые уже добавлены (хотя я думаю, что вы бы справились без DateTime и Guid ), а также добавьте System.OrdinalComparer .

Загвоздка в том, что System.OrdinalComparer это внутренний класс, поэтому вам придется получить тип с помощью отражения.

Редактировать:

System.OrdinalComparer является частью mscorlib сборки. В принципе, вы можете получить его тип следующим образом:

 Type[] types = typeof( string ).Assembly.GetTypes();
  

и затем вы можете получить требуемый тип по имени (используя Linq, добавьте необходимые инструкции using).

 Type type = types.Where( x => x.FullName == "System.OrdinalComparer" );
  

Предыдущие две строки можно объединить в одну, для простоты это делается с использованием двух строк.

Если вам нужны более подробные сведения, просто скажите.

Комментарии:

1. Я пытался, но получаю точно такую же ошибку. Я удалил атрибуты [ServiceKnownType] из интерфейса контракта и добавил атрибут [ServiceKnownType («GetKnownType»)] к самому классу. частный статический тип[] GetKnownTypes() { Тип[] corTypes = typeof(строка). Сборка. GetTypes(); Введите ordinalCompareType = (из t в corTypes, где t.FullName == «Система. OrdinalComparer» выберите t). FirstOrDefault(); Type[] types = new[] { ordinalCompareType, typeof(MembershipUserDTO) }; возвращаемые типы; } К сожалению, это не имело никакого значения.

2. @Sisiutl: Вы перестроили и повторно запустили службу, а затем обновили ссылку на службу?

3. Много раз 🙂 Есть ли способ определить, какой класс использует Ordinal Comparer? Мой DTO использует только string, int, bool и DateTime. Сервисные методы принимают и возвращают bool, int, string, Guid, DTO, List<DTO> и NameValueCollection. Может ли это быть NameValueCollection?

4. @Sisiutl: На самом деле, это базовый класс NameValueCollection (может быть легко определен с помощью Reflector).