why WCF service don't return list<>? - wcf

When i add/edit the service client, if i click on the "Advanced ..." button i will see an option allowing me to choose the collection type for my client proxy . The default is System.Array. When I change to System.Collaction.Generic.List and click Add proxy create. But in my method return value i see type[] but not List, why? What i do wrong?
this is class:
[DataContract]
public class Asset
{
[DataMember]
public decimal AssetId { get; set; }
[DataMember]
public string AssetName { get; set; }
}

when you generate proxy class choise List instead Array

Related

WCF return type is object

I have a WCF method:
public IQueryable<AmenitySummary> GetAmenities(string searchTerm)
Now, AmenitySummary is defined thus
[DataContract]
public class AmenitySummary
{
[DataMember]
public int AmenityId { get; set; }
[DataMember]
public string Amenity { get; set; }
[DataMember]
public string LowerCaseAmenity { get; set; }
}
In my client side solution I have a project in which I call this method. The problem is that the signature in the Reference.cs file is this
public object GetAmenities(string searchTerm) {
return base.Channel.GetAmenities(searchTerm);
}
How comes? Why isn't the return type IQueryable<AmenitySummary>? What am I missing?
Not only that, but when I try to use AmenitySummary on the client side I can't do it as it's not recognised. I think this is linked.
Thanks,
S
IQueryable is not serialiable without specific references (see svcutil.exe /references).
Otherwise use a WCF DataService (OData) or return an array of AmenitySummary from the service. In the later case you can convert the array to an IQuaryable instance.
I think it's because of IQueryable. You probably need to expose it too.
See this post:
Expose IQueryable Over WCF Service

.NET WebAPI Serialization k_BackingField Nastiness

When i serialize the following:
[Serializable]
public class Error
{
public string Status { get; set; }
public string Message { get; set; }
public string ErrorReferenceCode { get; set; }
public List<FriendlyError> Errors { get; set; }
}
I get this disgusting mess:
<ErrorRootOfstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Printmee.Api">
<_x003C_Errors_x003E_k__BackingField>
An exception has occurred. Please contact printmee support
</_x003C_Errors_x003E_k__BackingField>
<_x003C_LookupCode_x003E_k__BackingField>988232ec-6bc9-48f3-8116-7ff7c71302dd</_x003C_LookupCode_x003E_k__BackingField>
</ErrorRootOfstring>
What gives? How can i make this pretty? JSON responses also contain the k_BackingField
By default you don't need to use neither [Serializable] nor [DataContract] to work with Web API.
Just leave your model as is, and Web API would serialize all the public properties for you.
Only if you want to have more control about what's included, you then decorate your class with [DataContract] and the properties to be included with [DataMember] (because both DCS and JSON.NET respsect these attributes).
If for some reason, you need the [Serializable] on your class (i.e. you are serializing it into a memory stream for some reason, doing deep copies etc), then you have to use both attributes in conjunction to prevent the backing field names:
[Serializable]
[DataContract]
public class Error
{
[DataMember]
public string Status { get; set; }
[DataMember]
public string Message { get; set; }
[DataMember]
public string ErrorReferenceCode { get; set; }
[DataMember]
public List<FriendlyError> Errors { get; set; }
}
There is a more general solution: you can configure the Json Serializer to ignore the [Serializable] attribute, so that you don't have to change the attributes in your classes.
You should make this configuration change in the application start, i.e. in Global.asax Application_Start event:
var serializerSettings =
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;
var contractResolver =
(DefaultContractResolver)serializerSettings.ContractResolver;
contractResolver.IgnoreSerializableAttribute = true;
You can also make other changes to the Json serialization, like specifying formats for serializing dates, and many other things.
This will only apply to the Web API JSON serialization. The other serializations in the app (Web API XML serialization, MVC JsonResult...) won't be affected by this setting.
Try using DataContract instead of Serializable for marking your class. For more detail on why, look at this good blog post on serializing automatic properties.
The [DataContract] attributes dosn't worked for me, so it was not an option.
XmlSerializer ignores [XmlAttribute] in WebApi
The above resolution solved it for me.
GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;

Send a list with appointments through WCF

I would like to send a list of Appointments through WCF. My Interface looks like this:
[ServiceContract]
public interface IServices
{
[OperationContract]
string addAppointments(List<Appointment> appointmentList);
}
If I call my WCF Service I'm always getting the following error:
Type 'Microsoft.Exchange.WebServices.Data.Appointment' cannot be
serialized. Consider marking it with the DataContractAttribute
attribute, and marking all of its members you want serialized with the
DataMemberAttribute attribute. See the Microsoft .NET Framework
documentation for other supported types.
My Service currently looks like this:
class Service : IServices
{
public string addAppointments(List<Appointment> appointmentList)
{
foreach (Appointment app in appointmentList)
{
Console.WriteLine(app.Organizer.Name);
}
return "true";
}
}
It's not your service that's at fault, it's the class your passing, Appointment.
Start by adding [DataContract] to your class. then [DataMember] to each of the properties you'd like to pass.
For example, if you started with:
public class Appointment{
public DateTime Date { get; set; }
public string Name { get; set; }
}
You can make it serializable by WCF's DataContractSerializer by adding those attributes:
[DataContract]
public class Appointment{
[DataMember]
public DateTime Date { get; set; }
[DataMember]
public string Name { get; set; }
}

DTOs and WCF RIA

I have a DTO which has a collection within it of another DTO which I populate server-side and send to the client. However, this inner DTO collection is not returned to the client.
I believe I need to use the [Include] and [Association] attributes so that WCF RIA services knows what to do, however my issue with this is there is no real association as such between the main DTO and the inner DTO collection, I am just using it to aggregate data from various sources for return to the client.
Is my understanding wrong in what I am trying to achieve, if not how do I get WCF RIA to send this inner DTO collection.
I should add that I am using automapper and want to achieve it using such.
Here is an example, I want to send back to the client in one chunk;
The competencies that the employee has.
The competencies that the employee requires for their job.
The GAP, which is the difference between 1 and 2.
public class CompetencyRequirementsDto
{
[Key]
public string CompanyId { get; set; }
[Key]
public string EmployeeNo { get; set; }
public string JobId { get; set; }
[Include]
[Association("EmployeeCompetencies","CompanyId, EmployeeNo","CompanyId, EmployeeNo")]
public IList<EmployeeCompetencyDto> EmployeeCompetencies { get; set; }
[Include]
[Association("JobCompetencies","JobId, CompanyId","JobId, CompanyId")]
public IList<JobCompetencyDto> JobCompetencies { get; set; }
[Include]
[Association("CompetencyGap", "JobId, CompanyId", "JobId, CompanyId")]
public IList<JobCompetencyDto> CompetencyGap { get; set; }
} }
Now item 1 works fine, but 2 and 3 don't? What I have found is that my DTO is created ok server side but when it gets to the client CompetencyGap(even when it has no values) has
been given JobCompetencies values.
If you are using ADO.Net Entity data model and using RIA Services against them then you have got an option to create associated metadata.
So to get the reference entities at you client side we need to modify both the our corresponding meta-data and as well as well the function of the domain service class which is fetching your data .
Here I am giving an example...
1. Just add [Include] attribute at the the top of the referenced data for example.
[MetadataTypeAttribute(typeof(Customer.CustomerMetadata))]
public partial class Customer
{
// This class allows you to attach custom attributes to properties
// of the Customer class.
//
// For example, the following marks the Xyz property as a
// required property and specifies the format for valid values:
// [Required]
// [RegularExpression("[A-Z][A-Za-z0-9]*")]
// [StringLength(32)]
// public string Xyz { get; set; }
internal sealed class CustomerMetadata
{
// Metadata classes are not meant to be instantiated.
private CustomerMetadata()
{
}
public int CustomerID { get; set; }
public string EmailAddress { get; set; }
public string FullName { get; set; }
[Include]
public EntityCollection<Order> Orders { get; set; }
public string Password { get; set; }
}
}
2. Modify the function in the domain service and add include there also for example.
public IQueryable<Customer> GetCustomers()
{
var res = this.ObjectContext.Customers.Include("Orders");
return res;
}
In your case the first part is done you just need to modify your domain service query to get reference entities.

WCF client side List<>

I got a WCF service with a method (GetUserSoftware)to send a List to a client.
the software I have defined like this:
[DataContract]
public class Software
{
public string SoftwareID { get; set; }
public string SoftwareName { get; set; }
public string DownloadPath { get; set; }
public int PackageID { get; set; }
}
the method is going through my db to get all software availeble to the clien, and generates a list of that to send back to the client.
problem is i on the client side the list is turned into an array. and every item in that array dont contain any of my software attributs.
i have debugged my way through the server side. and seen that the list its about to send is correct. with the expected software and attributs in it.
any one know how to work around this or know what i can do ?
Did you forget [DataMemeber] attribute on your properties?
When you use DataContract attribute for a type you have to use DataMember attribute for each property or field you want to serialize and transfer between service and client. Collections are by default created as arrays. If you don't like it you can change this behavior in Add Service Reference window -> Advanced settings where you can select which collection type should be used.
First off, each of the properties that you want to serialize should have the [DataMember] attribute:
[DataContract]
public class Software
{
[DataMember]
public string SoftwareID { get; set; }
[DataMember]
public string SoftwareName { get; set; }
[DataMember]
public string DownloadPath { get; set; }
[DataMember]
public int PackageID { get; set; }
}
Second, the translation to an Array would be handled by the client, not the server.
You can mantain List instead of array on the clien when you add the Service Reference: click the "advanced" button and change the collection type to the one you want.
I was suffering with same problem and now I solved it! It was a ServiceKnownType problem. If you have a in known type loader we have to add runtime Type like;
Type aaa = Type.GetType("System.Collections.Generic.List`1[[ProjectName.BusinessObjects.Bank, ProjectName.BusinessObjects, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null]]");
knownTypes.Add(aaa);
Anyone having same problem can try this. It's working in my environment!