我正在构建一个使用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());
}
我将DTO用于所有使用[DataContract] / [DataMember]属性的请求和响应。该服务正确接受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尝试序列化方法调用的db条目。我认为这不应该是一个问题,因为我使用DTO进行响应,并且在响应构建方面没有任何意义。我google了一下,我尝试了一些解决方案,如
Configuration.ProxyCreationEnabled = false;
和
Configuration.LazyLoadingEnabled = false;
但他们没有工作。当然,我还将DataContract和DataMember属性添加到我的所有POCO中,因为错误消息指示但无济于事。
更新:这是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; }
}
答案 0 :(得分:0)
尝试使用数据协定和具有数据成员属性的属性来修饰类。
答案 1 :(得分:0)
WCF似乎无法序列化我在通用存储库类方法中使用的IQueryable类型来返回数据库结果的集合。它通过使用List来工作,如果你问我,这是非常icky。如果有人比使用List有更好的建议,请提及它。