【问题标题】:WCF serialisation error with EF 6EF 6 的 WCF 序列化错误
【发布时间】:2014-10-23 00:07:19
【问题描述】:

我正在构建一个使用 EF 6 访问 POCO 的 RESTful WCF 服务。我还使用 Ninject 和存储库模式来访问数据库。这是我的服务设置:

配置

 <serviceBehaviors>
    <behavior name="commonServicebehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="sbLoginSAS">
      <transportClientEndpointBehavior>
        <tokenProvider>
          <sharedAccessSignature keyName="RootManageSharedAccessKey" key="oJh2klf242iwISUDcsTQHeR/3W3FlQTQte/M=" />
        </tokenProvider>
      </transportClientEndpointBehavior>
      <webHttp defaultOutgoingResponseFormat="Json" />
      <serviceRegistrySettings discoveryMode="Public" />
    </behavior>

合同

[ServiceContract]
public interface ILoginService
{
    [OperationContract]
    [WebInvoke(UriTemplate = "")]
    ErrorCollectionDTO Login(LoginRequestDTO loginRequest);
}

实施

class LoginService : ILoginService
{
    private readonly ILoginValidator _loginValidator;
    private readonly IErrorMapper _errorMapper;
    private readonly IEncryptor _encryptor;
    private readonly IUserManager _userManager;

    public LoginService(ILoginValidator loginValidator, IErrorMapper errorMapper, IEncryptor encryptor, IUserManager userManager)
    {
        _loginValidator = loginValidator;
        _errorMapper = errorMapper;
        _encryptor = encryptor;
        _userManager = userManager;
    }

    public ErrorCollectionDTO Login(LoginRequestDTO loginRequest)
    {
        //Validate the request
        var completeSummary = _loginValidator.Validate(loginRequest);

        //Maps validation errors to a response DTO
        var errorCollectionDTO = _errorMapper.Transform(completeSummary);

        //If request not valid, return errors
        if (!errorCollectionDTO.IsValid) return errorCollectionDTO;

        //At this point, user is correctly authenticated
        //so we prepare and send him an authorization token
        var user = _userManager.GetUser(loginRequest.CPR);
        var token = _encryptor.Encrypt(loginRequest.CPR);

        user.SecurityToken = new SecurityToken
        {
            Token = token,
            ValidUntil = DateTime.Now.AddMinutes(5)
        };

        _userManager.UpdateUser(user);

        return new LoginResponseDTO(errorCollectionDTO, token.ToString());
    }

我对所有使用 [DataContract] / [DataMember] 属性的所有请求和响应都使用 DTO。该服务正确接受 JSON 请求。但是我在该行中遇到错误:

var completeSummary = _loginValidator.Validate(loginRequest);

当调用方法尝试使用 _userManager.GetUser(entity.CPR) 通过其存储库检索实体的条目时:

 private IEnumerable<IError> ValidateEntity(LoginRequestDTO entity)
    {
        if (entity == null)
            yield return new Error("Login request was null or invalid");
        else
        {
            var user = _userManager.GetUser(entity.CPR);

            if (user == null)
                yield return new Error("User doesn't exist or password is wrong");
        }
    }


Type 'System.Data.Entity.DbSet`1[ITU.MAP.Domain.Model.User]' cannot be serialized.
Consider marking it with the DataContractAttribute attribute, and marking all of its
members you want serialized with the DataMemberAttribute attribute.  If the type is
a collection, consider marking it with the CollectionDataContractAttribute.

据我了解,WCF 尝试序列化方法调用的数据库条目。我认为这应该不是问题,因为我使用 DTO 进行响应,而这与响应构造相去甚远。我用谷歌搜索并尝试了一些解决方案,例如

Configuration.ProxyCreationEnabled = false;

Configuration.LazyLoadingEnabled = false;

但他们没有工作。当然,我还向我的所有 POCO 添加了 DataContract 和 DataMember 属性,如错误消息所示,但无济于事。

更新:这是 WCF 尝试序列化的 POCO。我还尝试使用仅用 [DataContract] 和 [DataMember] 装饰的其他非抽象类,但会发生相同的错误。 KnownType 中的子类型也使用上述属性正确修饰。

[DataContract(IsReference = true)]
[KnownType(typeof(Paramedic))]
[KnownType(typeof(Resident))]
[Table("Users")]
public abstract class User : IIdentifiable
{
    [Key]
    [DataMember]
    [DisplayName("Id")]
    public int Id { get; set; }

    [DataMember]
    [DisplayName("CPR")]
    public string CPR { get; set; }

    [DataMember]
    [DisplayName("Password hash")]
    public byte[] Password { get; set; }

    [DataMember]
    [DisplayName("Name")]
    public string Name { get; set; }

    [DataMember]
    [DisplayName("Surname")]
    public string Surname { get; set; }

    [DataMember]
    [DisplayName("Region")]
    public int RegionId { get; set; }

    [DataMember]
    [DisplayName("Region")]
    [ForeignKey("RegionId")]
    public virtual Region Region { get; set; }

    [DataMember]
    [DisplayName("Age")]
    public int Age { get; set; }

    [DataMember]
    [DisplayName("Blood type")]
    public BloodType BloodType { get; set; }

    [DataMember]
    [DisplayName("Rhesus")]
    public Rhesus Rhesus { get; set; }

    [DataMember]
    public int? SecurityTokenId { get; set; }

    [DataMember]
    [DisplayName("Security token")]
    [ForeignKey("SecurityTokenId")]
    public virtual SecurityToken SecurityToken { get; set; }

    [DataMember]
    public virtual ICollection<Allergy> Allergies { get; set; }

    [DataMember]
    public virtual ICollection<Condition> Conditions { get; set; }

    [DataMember]
    public virtual ICollection<Prescription> Prescriptions { get; set; }
}

【问题讨论】:

    标签: c# .net entity-framework wcf


    【解决方案1】:

    尝试用数据契约装饰类,用数据成员属性装饰属性。

    【讨论】:

    • 来自 OP 的帖子:“我还向我的所有 POCO 添加了 DataContract 和 DataMember 属性,如错误消息所示,但无济于事。”
    【解决方案2】:

    WCF 似乎无法序列化我在通用存储库类方法中用于返回数据库结果集合的 IQueryable 类型。它通过使用 List 来代替,如果你问我,这很恶心。如果有人有比使用 List 更好的建议,请务必提及。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      • 1970-01-01
      • 2012-05-25
      • 1970-01-01
      • 2012-12-15
      相关资源
      最近更新 更多