Deserialization Error while returning the Object from WCF Service - wcf

I'm getting below shown error while returning the Activity object array.Not able understand where things are going wrong.Can any one help me with this .
Here is the error
End element 'ActivityTypeId' from namespace
'http://schemas.datacontract.org/2004/07/BusinessEntities' expected.
Found element 'a:Code' from namespace
'http://schemas.datacontract.org/2004/07/BusinessEntities'. Line 1,
position 450.
UI Related code:
protected void Page_Load(object sender, EventArgs e)
{
TimeSheetManagementServiceClient serviceClient = new TimeSheetManagementServiceClient("WSHttpBinding_ITimeSheetManagementService");
Activity[] activities=serviceClient.GetActivities();
GridView1.DataSource = activities;
GridView1.DataBind();
}
WCFService code
public class TimeSheetManagementService:ITimeSheetManagementService
{
public BusinessEntities.Activity[] GetActivities()
{
TimeSheetManagementDataController controller= new TimeSheetManagementDataController();
var activities = controller.GetActivities().Select(activity => new BusinessEntities.Activity()
{
Code = activity.Code,
Description = activity.Description,
Status =
(EntityStatus)
Enum.Parse(typeof(EntityStatus), ((activity.Status==true) ? 0 : 1).ToString()),
ActivityTypeId = new BusinessEntities.ActivityType()
{
Code=activity.ActivityType.Code,
Description = activity.ActivityType.Description,
Name = activity.ActivityType.Name
}
});
return activities.ToArray();
}
}
Service Contract
[ServiceContract]
interface ITimeSheetManagementService
{
[OperationContract]
Activity[] GetActivities();
}
Data Contract
[DataContract]
public class Activity
{
[DataMember]
public string Code { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public EntityStatus Status { get; set; }
[DataMember]
public ActivityType ActivityTypeId { get; set; }
}
[DataContract]
public enum EntityStatus
{
[EnumMember]
Active=0,
[EnumMember]
Inactive=1
}
[DataContract]
public class ActivityType
{
[DataMember]
public string Code { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
}

i`m not sure but i think the issue is the alphabetical order of the datamember of your Activity class. just for testing, consider specifying the order property in the Datamember attribute.
http://msdn.microsoft.com/en-us/library/ms729813%28v=vs.90%29.aspx
hope this will help

Related

applying an object with a ICollection<Enum> type

In an ASP.NET 3.1 CORE project, using EF, I am trying to implement an object that holds a type of ICollection<Enum> type.
the problem is after reading some tutorials and trying to migrate it to my database something seems off, I will attach screenshots and code for more understanding.
this is the object class :
public class UsersCredentialsModel
{
[Key]
public string UserId { get; set; }
public ICollection<ServiceModel> Services { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Hash { get; set; }
}
The ServiceModel class:
public class ServiceModel
{
[Key]
public string ServiceId { get; set; }
public Service Service { get; set; }
}
The Service Enum Class:
public enum Service : int
{
Badoo = 0,
Tinder = 1,
Grinder = 2,
OkCupid = 3
}
This is the AppDbContext class:
public class AppDbContext : IdentityDbContext<ApplicationUser>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Message>().Property(m => m.Service).HasConversion<int>();
builder.Entity<ApplicationUser>().HasMany<Message>(m => m.Messages).WithOne(u =>
u.User).IsRequired();
builder.Entity<ServiceModel>().Property(m => m.Service).HasConversion<int>();
builder.Entity<UsersCredentialsModel>().HasMany(s => s.Services);
base.OnModelCreating(builder);
}
public DbSet<UsersCredentialsModel> UsersCredentialsModels { get; set; }
public DbSet<ServiceModel> ServiceModel { get; set; }
public DbSet<Message> Messages { get; set; }
public DbSet<CookieModel> CookieModel { get; set; }
public DbSet<ProjectionModel> ProjectionModel { get; set; }
}
This is a picture of the UsersCredentialsModel database schema:
** I believe that there should be a filed called "ServiceId" corresponding to the Id of the second table.
and finally a picture of the ServiceModel schema:
from what I understood you can't implement ICollection of type ENUM and you have to wrap it in a class so basically you need an object to hold the ENUM with an ID and another Id that holds the userId.
The problem is that UserCredentialsModel table should hold an Id property of ServiceId coming from ServiceModel table.
because the class has a field of ICollection but when migrating it does nothing

How to use AutoMapper to map OData enum string in json request dto to entity enum property

I am working on a new ASP.NET Core 3.1.1 API with Microsoft.AspNetCore.OData v 7.3.0, AutoMapper v9.0.0 and Microsoft.AspNetCore.Mvc.NewtonsoftJson v3.1.1
I am getting the following error when I make a POST to the Accounts endpoint using Postman v7.18.0;
AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
I have reviewed the similar questions list when creating this question but was unable to find a solution.
In reviewing google searches for AutoMapper OData Enums all I could find were the recommendation to decorate my dto class with...
[AutoMap(typeof(Account))]
... and to decorate my dto enum properties with ...
[JsonConverter(typeof(StringEnumConverter))]
However, I still get the error. I found references to using an AutoMapperProfile class with a mapper defined as
CreateMap<Account, AccountModel>().ReverseMap();
But it appears that AutoMapper v9.0.0 no longer has a CreateMap method. My understanding was that adding the [AutoMap(typeof(Account))] to the dto class had the same effect as creating the map in the profile class.
I feel like I am going in circles at this point here so I though I would reach out to the SO community. I am sure it is something simple, I am just not seeing it.
Here is my POST request body from Postman;
{
"#odata.context": "https://localhost:44367/v1/$metadata#Accounts",
"AccountName": "Test Provider",
"AccountType": "Provider",
"IsTaxExempt": false,
"Status": "Active"
}
Here is my AccountsController Post method;
[ODataRoute]
[Produces("application/json;odata.metadata=minimal")]
[ProducesResponseType(typeof(AccountModel), Status201Created)]
[ProducesResponseType(Status400BadRequest)]
public async Task<IActionResult> Post([FromBody] AccountModel record)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
record.Id = new Guid();
var entity = _mapper.Map<Account>(record);
_context.Add(entity);
await _context.SaveChangesAsync();
var createdRecord = _mapper.Map<AccountModel>(entity);
return Created(createdRecord);
}
Here is my Account entity class;
public class Account : EntityBase
{
[Required]
[Column(TypeName = "nvarchar(50)")]
[MaxLength(50)]
public string AccountName { get; set; }
public AccountTypes AccountType { get; set; }
public bool IsTaxExempt { get; set; }
}
Here is the EntityBase class;
public class EntityBase
{
[Required]
public Guid Id { get; set; }
public DateTimeOffset? DateTimeCreated { get; set; } = DateTime.UtcNow;
public DateTimeOffset? DateTimeLastModified { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public StatusTypes Status { get; set; }
public bool DeleteFlag { get; set; }
}
Here is my Account DTO class;
[Filter, Count, Expand, OrderBy, Page, Select]
[AutoMap(typeof(Account))]
public class AccountModel : BaseModel
{
[Required]
[MaxLength(50)]
public string AccountName { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public AccountTypes AccountType { get; set; }
public bool IsTaxExempt { get; set; }
}
Here is my BaseModel class;
[Select, Filter]
public class BaseModel
{
public Guid Id { get; set; }
public DateTimeOffset DateTimeCreated { get; set; } = DateTime.UtcNow;
public DateTimeOffset DateTimeLastModified { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public StatusTypes Status { get; set; }
public bool DeleteFlag { get; set; }
}
And here are my Enums for AccountTypes and StatusTypes
public enum AccountTypes
{
Customer = 0,
Reseller = 1,
Provider = 2,
}
public enum StatusTypes
{
Active = 0,
Inactive = 1,
}
Any ideas?
It turns out that I needed to create an instance of an AutoMapper MapperConfiguration and assign it to the mapper.
I ended up putting in in the constructor of the Controller, for example;
public AccountsController(CdContext context, IMapper mapper)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
var config = new MapperConfiguration(cfg => cfg.CreateMap<Account, AccountModel>().ReverseMap());
_mapper = new Mapper(config);
}
After I did this, everything worked as expected.
Here is a link to AutoMappers docs on the subject.

howto initialize a wcf class

Im trying to use a Class in a WCF service. When im calling the
u.attributeChanges.Add(a);
i get:
"Object reference not set to an instance of an object"
If create the classes in the client application it's working.
UpdateChanges Class
[DataContract]
public class UpdateChanges
{
private void Initialize()
{
this.attributeChanges = new List<AttributeChanges>();
}
public UpdateChanges()
{
this.Initialize();
}
[DataMember]
public string objectGuid { get; set; }
[DataMember]
public Utilities.ObjectTypes objectType { get; set; }
[DataMember]
public Utilities.ChangeType changeType{ get; set; }
[DataMember]
public List<AttributeChanges> attributeChanges { get; set; }
[OnDeserializing]
public void OnDeserializing(StreamingContext ctx)
{
this.Initialize();
}
}
AttributeChanges class
[DataContract]
public class AttributeChanges
{
[DataMember]
public string attributeName { get; set; }
[DataMember]
public string attributeValue { get; set; }
}
Client Code:
Service.DirsyncServiceClient proxyClient;
proxyClient = Utilities.GetProxy("http://192.168.1.45/vDir/Service.svc");
Service.UpdateChanges u = new Service.UpdateChanges();
Service.AttributeChanges a = new Service.AttributeChanges();
a.attributeName = "Attribute1";
a.attributeValue = "Value1";
u.attributeChanges.Add(a);
proxyClient.SaveObject(u);
Anyonw know how to solve this?
You're using a generated client code.
The problem is that the client generates this code on base of the WSDL xlm. The code in the CTOR doesn't generated in the client because the client can't be aware of this code.
You have a few options-
1. Use a shared DLL with the data contract instead of generating it via a web reference.
2. Implement it yourself in a 'partial' class.

Not able to pass List<FilterData> using WCF with wsHttpBinging

I am not able to pass List using WCF with wsHttpBinging. List is a property of FilterResponse class.
Getting the following error.
-Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
//Following is the code.
[DataContract(Namespace = "Abc.Wao.Entity.Response")]
[CollectionDataContract]`
public class FilterResponse : Alcoa.Wao.Entity.Response.Response
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists"), DataMember]
public List<FilterData> FilterData { get; set; }
}
[KnownType(typeof(FilterResponse))]
[CollectionDataContract]
[DataContract(Namespace = "Abc.Wao.Entity.Response")]
public class Response
{
public Response()
{ }
[DataMember]
public string AuthToken { get; set; }
[DataMember]
public string Fault { get; set; }
[DataMember]
public Exception Exception { get; set; }
[DataMember]
public string SessionContext { get; set; }
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class WaoService : IWaoService
{
public FilterResponse GetFilterDetails()
{
FilterResponse res = null;
//Call factory
res = Abc.Wao.Factory.CommonFactory.GetFilterDetails();
return res;
}
}
//------------------------------------------------------
[ServiceContract]
[ServiceKnownType(typeof(FilterResponse))]
[ServiceKnownType(typeof(Response))]
public interface IWaoService
{
[OperationContract]
FilterResponse GetFilterDetails();
}
Your property in the DataContract is missing a DataMember attribute:
[DataMember]
public List<FilterData> FilterData { get; set; }

wcf serialization problem

I have a type MyParameter that i pass as a parameter to a wcf service
[Serializable]
public class MyParameter : IXmlSerializable
{
public string Name { get; set; }
public string Value { get; set; }
public string Mytype { get; set; }
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XElement e = XElement.Parse(reader.ReadOuterXml());
IEnumerable<XElement> i = e.Elements();
List<XElement> l = new List<XElement>(i);
Name = l[0].Name.ToString();
Value = l[0].Value.ToString();
Mytype = l[0].Attribute("type").Value.ToString();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteStartElement(Name);
writer.WriteAttributeString("xsi:type", Mytype);
writer.WriteValue(Value);
writer.WriteEndElement();
}
#endregion
}
The service contract looks like this:
[ServiceContract]
public interface IOperation
{
[OperationContract]
void Operation(List<Data> list);
}
Where data defines a data contract
[DataContract]
public class Data
{
public string Name { get; set; }
public List<MyParameter> Parameters{ get; set; }
}
When I run the service and test it
I get rhe exception in readXml of MyParameter
"the prefix xsi is not defined"
xsi should define the namespace "http://w3.org/2001/xmlschema-instance"
How do I fix the problem
I am very new to this so a sample code will be very very very helpful
thanks
Add:
writer.WriteAttributeString("xmlns","xsi", null,#"http://w3.org/2001/xmlschema-instance");