Supposing that we have the following code for WCF service and a database with an Employee table.
Why use [DataContract] and what are benefits of using all [DataMember] ?
We can use all Employee details without using [DataContract].
[ServiceContract]
public interface IEmployeeService
{
[OperationContract]
Employee GetEmployeeDetails(int EmpId);
}
[DataContract]
public class Employee
{
private string m_Name;
private int m_Age;
private int m_Salary;
[DataMember]
public string Name
{
get { return m_Name; }
set { m_Name = value; }
}
[DataMember]
public int Age
{
get { return m_Age; }
set { m_Age = value; }
}
[DataMember]
public int Salary
{
get { return m_Salary; }
set { m_Salary = value; }
}
}
Implementatin of Service:
public class EmployeeService : IEmployeeService
{
public Employee GetEmployeeDetails(int empId)
{
Employee empDetail = new Employee();
return empDetail;
}
}
And our Client:
private void btnGetDetails_Click(object sender, EventArgs e)
{
EmployeeServiceClient objEmployeeClient = new EmployeeServiceClient();
Employee empDetails;
empDetails = objEmployeeClient.GetEmployeeDetails(empId);
}
Related
I use DTO class in API layer and I struggle to map DTO class to "model" class in generic Repository.cs in core layer.
Repository.cs :
namespace DTOMap.Core.Repository.Generic
{
public class Repository<T> : IRepository<T> where T : class
{
private DTOMapContext _context;
private DbSet<T> _table;
private IMapper _mapper;
public Repository(DTOMapContext context)
{
_context = context;
_table = _context.Set<T>();
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<MyMapper>();
});
_mapper = config.CreateMapper();
}
public T Add(T obj)
{
// Here how to use My Mapper to save a book or an author generically
// Sth like :
// temp = _table.Add(_mapper.Map<T>(obj)); Here I want to map Dto to model to save in the db
// return = (_mapper.Map<T>(temp)); Here I want to map Model to DTO to collect it in API
// but I can't have a reference to TDTO
throw new NotImplementedException();
}
}
}
I show you the other classes that I find useful (I only implement Add function for this example and I am a beginner in .Net) :
Author.cs
namespace DTOMap.Core.Models
{
[Table("Author")]
internal class Author
{
[Key]
public int id { get; set; }
[Required, MaxLength(255)]
public string firstName { get; set; }
[Required,MaxLength(255)]
public string lastName { get; set; }
}
}
Book.cs
namespace DTOMap.Core.Models
{
[Table("Book")]
internal class Book
{
[Key]
public int id { get; set; }
[Required,MaxLength(255)]
public string name { get; set; }
[Required]
public int authorId { get; set; }
[Required]
public Author author { get; set; }
}
}
AuthorDTO.cs
namespace DTOMap.Domain.DTO
{
public class AuthorDTO
{
public int id { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
}
}
BookDTO.cs
namespace DTOMap.Domain.DTO
{
public class BookDTO
{
public int id { get; set; }
public string name { get; set; }
public int authorId { get; set; }
public AuthorDTO author { get; set; }
}
}
IRepository.cs
namespace DTOMap.Domain.Interface
{
public interface IRepository<T>
{
T Add(T obj);
}
}
MyMapper.cs
namespace DTOMap.Core
{
public class MyMapper : Profile
{
public MyMapper()
{
CreateMap<Book, BookDTO>();
CreateMap<BookDTO, Book>();
CreateMap<Author, AuthorDTO>();
CreateMap<AuthorDTO, Author>();
}
}
}
program.cs
... Some Fcts
builder.Services.AddTransient<IRepository<BookDTO>, BookRepository>();
builder.Services.AddTransient<IRepository<AuthorDTO>, AuthorRepository>();
... Some Fcts
If you need any other information, please ask me.
I'm designing a profile page for users where they can edit their personal info. I'm using a PersonViewModel (which contains the current signed in person) to display the current info about the User. The fields to edit the user's info are bound to a validation model. After pressing the 'execute changes' button and I get a response of the server (HTTPStatusCode Ok + the altered user object), I alter the fields of the existing object according to the changes. Then I used setter injection to update my PersonViewModel... When debugging, I can see that my objects are all up-to-date but my view is still displaying the old info... What am I doing wrong?`
This is the code that get's executed when I press the button to execute my changes:
private async void ChangeInfoButton(object sender, RoutedEventArgs e)
{
User user;
List<ErrorInfo> errors;
if (_profileInformationValidationModel.TryGetUser(out user, out errors))
{
var response = await Session.Instance.DataProvider.UpdaterUserInfo(user);
if (response.IsSuccess)
{
/*SignedInUserInfo = AlteredUserInfo*/
Session.Instance.User.Information = user.Information;
_personViewModel.SetPerson(user.Information);
var d1 = new MessageDialog("Uw gegevens werden succesvol gewijzigd.");
d1.ShowAsync();
AnnulInfoButton(sender, e);
}
`
And this is the PersonViewModel:
public class PersonViewModel
{
private Person _person;
public void SetPerson(Person p)
{
_person = p;
}
public PersonViewModel(Person person)
{
_person = person;
}
public string Street
{
get { return _person.Street; }
}
public string HouseNumber
{
get { return _person.HouseNumber; }
}
public string Bus
{
get { return _person.Bus; }
}
public string Email
{
get { return _person.Email; }
}
Your view model should implement the INotifyPropertyChanged interface.
Look into using a framework like MVVM Light which does most of this work for you.
You can add it to your project using NuGet.
This is how your model and view-model should look:
public class Person
{
public string Street { get; set; }
public string HouseNumber { get; set; }
public string Bus { get; set; }
public string Email { get; set; }
}
public class PersonViewModel : System.ComponentModel.INotifyPropertyChanged
{
private Person _person;
public void SetPerson(Person person)
{
_person = person;
Street = person.Street;
HouseNumber = person.HouseNumber;
Bus = person.Bus;
Email = person.Email;
}
public PersonViewModel(Person person)
{
SetPerson(person);
}
#region Street (INotifyPropertyChanged Property)
private string _street;
public string Street
{
get { return _street; }
set
{
if (_street != value)
{
_street = value;
RaisePropertyChanged("Street");
}
}
}
#endregion
#region HouseNumber (INotifyPropertyChanged Property)
private string _houseNumber;
public string HouseNumber
{
get { return _houseNumber; }
set
{
if (_houseNumber != value)
{
_houseNumber = value;
RaisePropertyChanged("HouseNumber");
}
}
}
#endregion
#region Bus (INotifyPropertyChanged Property)
private string _bus;
public string Bus
{
get { return _bus; }
set
{
if (_bus != value)
{
_bus = value;
RaisePropertyChanged("Bus");
}
}
}
#endregion
#region Email (INotifyPropertyChanged Property)
private string _email;
public string Email
{
get { return _email; }
set
{
if (_email != value)
{
_email = value;
RaisePropertyChanged("Email");
}
}
}
#endregion
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string p)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(p));
}
}
}
I am using WCF WebAPI for creating REST service and EF4. While returning an object(of POCO class) which is having NavigationProperty, I am getting following Serialization exception:
Cannot serialize member Models.Customer.Orders of type System.Collections.Generic.ICollection`1[[Models.Order, Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] because it is an interface.
Following is the POCO class
[Serializable]
[DataContract(IsReference = true)]
[KnownType(typeof(Order))]
public partial class Customer
{
#region Primitive Properties
[DataMember]
public virtual int CustomerID { get; set; }
[DataMember]
public virtual string CustomerCode { get; set; }
[DataMember]
public virtual string Description { get; set; }
[DataMember]
public virtual string Comments { get; set; }
[DataMember]
public virtual bool DeleteFlag { get; set; }
[DataMember]
public virtual byte[] RowVersion { get; set; }
#endregion
#region Navigation Properties
[DataMember]
public virtual ICollection<Order> Orders
{
get
{
if (_order == null)
{
var newCollection = new FixupCollection<Order>();
newCollection.CollectionChanged += FixupOrders;
_order = newCollection;
}
return _order;
}
set
{
if (!ReferenceEquals(_order, value))
{
var previousValue = _order as FixupCollection<Order>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupOrders;
}
_order = value;
var newValue = value as FixupCollection<Order>;
if (newValue != null)
{
newValue.CollectionChanged += FixupOrders;
}
}
}
}
private ICollection<Order> _order;
#endregion
#region Association Fixup
private void FixupOrders(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Order item in e.NewItems)
{
item.Customer = this;
}
}
if (e.OldItems != null)
{
foreach (Order item in e.OldItems)
{
if (ReferenceEquals(item.Customer, this))
{
item.Customer = null;
}
}
}
}
#endregion
}
The method in service is as follows:
[WebGet(UriTemplate = "Customer",
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml)]
public List<Customer> Get()
{
CustEntities context = new CustEntities();
return context.Customer.Include("Orders").ToList();
}
Any help in above regard is highly appreciable.
Thanks
I don't think you can serialize Properties as interfaces in this way, otherwise the deserializer wouldn't know which concrete type to create when the object is deserialized.
Can you change your ICollection property to a concrete type like List<T>?
I'm having the following error in my wcf client.
NetDispatcherFaultException was unhandled.
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:GetVehicleResult. The InnerException message was 'Error in line 1 position 266. Element 'http://tempuri.org/:GetVehicleResult' contains data from a type that maps to the name 'http://schemas.datacontract.org/2004/07/WCFServer:Car'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'Car' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.
Can anyone help me where is the fault.
WCF Server
IVehicle
--------
[ServiceContract]
public interface IVehicleService
{
[OperationContract]
Vehicle GetVehicle(int type);
[OperationContract]
int GetNumberOfWheels(Vehicle vehicle);
}
VehicleService
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class VehicleService : IVehicleService
{
public Vehicle GetVehicle(int type)
{
switch (type)
{
case 0:
return new Car()
{
ID = 10,
Brand = "Volvo",
SteeringWheelPosition = "left"
};
case 1:
return new bike()
{
ID = 11,
Brand = "Scott",
HasFrontWheelBreak = true
};
case 2:
return new Kidsbike()
{
ID = 12,
Brand = "Kid Scott",
HasFrontWheelBreak = false,
HasSupportingWheels = true
};
default:
return null;
}
}
public int GetNumberOfWheels(Vehicle vehicle)
{
return vehicle.NoOfWheels;
}
}
abstract class
[KnownType(typeof(Car))]
[KnownType(typeof(bike))]
[DataContract]
public abstract class Vehicle
{
[DataMember]
public int ID { get; set; }
abstract public int NoOfWheels { get; }
[DataMember]
public string Brand { get; set; }
}
concrete classes
[DataContract]
public class Car : Vehicle
{
override public int NoOfWheels { get { return 4; } }
[DataMember]
public string SteeringWheelPosition { get; set; }
}
[KnownType(typeof(Kidsbike))]
[DataContract]
public class bike : Vehicle
{
override public int NoOfWheels { get { return 2; } }
[DataMember]
public bool HasFrontWheelBreak { get; set; }
}
[DataContract]
public class Kidsbike : bike
{
[DataMember]
public bool HasSupportingWheels { get; set; }
}
WCF Client
namespace WCFClient
{
[ServiceContract]
public interface IVehicleService
{
[OperationContract]
Vehicle GetVehicle(int type);
[OperationContract]
int GetNumberOfWheels(Vehicle vehicle);
}
}
namespace WCFClient
{
[KnownType(typeof(Car))]
[KnownType(typeof(bike))]
[DataContract]
public abstract class Vehicle
{
[DataMember]
public int ID { get; set; }
abstract public int NoOfWheels { get; }
[DataMember]
public string Brand { get; set; }
}
[DataContract]
public class Car : Vehicle
{
override public int NoOfWheels { get { return 0; } }
[DataMember]
public string SteeringWheelPosition { get; set; }
}
[KnownType(typeof(Kidsbike))]
[DataContract]
public class bike : Vehicle
{
override public int NoOfWheels { get { return 0; } }
[DataMember]
public bool HasFrontWheelBreak { get; set; }
}
[DataContract]
public class Kidsbike : bike
{
[DataMember]
public bool HasSupportingWheels { get; set; }
}
}
private void btnGetVehicle_Click(object sender, EventArgs e)
{
Car carObj = (Car)fclient.GetVehicle(0);
}
just creating proxy in client side . I can able to call the service successfully, but in response im having the problem. I try with Knowntype attribute. Whats wrong in this.
The following code work fine without error.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService1 {
[ServiceKnownType(typeof(Car))]
[ServiceKnownType(typeof(bike))]
[ServiceKnownType(typeof(Kidsbike))]
[ServiceContract]
public interface IVehicleService {
[OperationContract]
Vehicle GetVehicle(int type);
[OperationContract]
int GetNumberOfWheels(Vehicle vehicle);
}
[DataContract]
public abstract class Vehicle
{
[DataMember]
public int ID { get; set; }
abstract public int NoOfWheels { get; }
[DataMember]
public string Brand { get; set; }
}
[DataContract]
public class Car : Vehicle
{
override public int NoOfWheels { get { return 0; } }
[DataMember]
public string SteeringWheelPosition { get; set; }
}
[KnownType(typeof(Kidsbike))]
[DataContract]
public class bike : Vehicle
{
override public int NoOfWheels { get { return 0; } }
[DataMember]
public bool HasFrontWheelBreak { get; set; }
}
[DataContract]
public class Kidsbike : bike
{
[DataMember]
public bool HasSupportingWheels { get; set; }
}
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class VehicleService : IVehicleService
{
public Vehicle GetVehicle(int type)
{
switch (type)
{
case 0:
return new Car()
{
ID = 10,
Brand = "Volvo",
SteeringWheelPosition = "left"
};
case 1:
return new bike()
{
ID = 11,
Brand = "Scott",
HasFrontWheelBreak = true
};
case 2:
return new Kidsbike()
{
ID = 12,
Brand = "Kid Scott",
HasFrontWheelBreak = false,
HasSupportingWheels = true
};
default:
return null;
}
}
public int GetNumberOfWheels(Vehicle vehicle)
{
return vehicle.NoOfWheels;
}
}
}
Svc file:
<%# ServiceHost Language="C#" Debug="true" Service="WcfService1.VehicleService" CodeBehind="Service1.svc.cs" %>
Testing service:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using WcfService1;
namespace Test {
class Program {
static void Main(string[] args) {
BasicHttpBinding hproxy = new BasicHttpBinding();
hproxy.MaxReceivedMessageSize = 2147483647;
hproxy.MaxBufferSize = 2147483647;
hproxy.MaxBufferPoolSize = 2147483647;
EndpointAddress eaddrr = new EndpointAddress("http://localhost:62807/Service1.svc");
ChannelFactory<IVehicleService> CFactoryobj1 = new ChannelFactory<IVehicleService>(hproxy, eaddrr);
IVehicleService isclientobj1 = CFactoryobj1.CreateChannel();
Car ve = (Car)isclientobj1.GetVehicle(0);
}
}
}
The KnownType should be used on the service contract interface itself not the vehicle class since it is the one that is returning the Vehicle object for one of its operations. Adding KnownType to the Vehicle class does nothing I think. because by default now, you don't need to add DataContract to your class for them to be useable in WCF. so you should have something like below.
[ServiceKnownType(typeof(Car))]
[ServiceKnownType(typeof(bike))]
[ServiceKnownType(typeof(Kidsbike))]
[ServiceContract]
public interface IVehicleService
{
[OperationContract]
Vehicle GetVehicle(int type);
[OperationContract]
int GetNumberOfWheels(Vehicle vehicle);
}
I have an object which has a property on it that has then has collections which i would like to not load in a couple situations. 98% of the time i want those collections fetched but in the one instance i do not. Here is the code I have... Why does it not set the fetch mode on the properties collections?
[DataContract(Name = "ThemingJob", Namespace = "")]
[Serializable]
public class ThemingJob : ServiceJob
{
[DataMember]
public virtual Query Query { get; set; }
[DataMember]
public string Results { get; set; }
}
[DataContract(Name = "Query", Namespace = "")]
[Serializable]
public class Query : LookupEntity<Query>, DAC.US.Search.Models.IQueryEntity
{
[DataMember]
public string QueryResult { get; set; }
private IList<Asset> _Assets = new List<Asset>();
[IgnoreDataMember]
[System.Xml.Serialization.XmlIgnore]
public IList<Asset> Assets { get { return _Assets; } set { _Assets = value; } }
private IList<Theme> _Themes = new List<Theme>();
[IgnoreDataMember]
[System.Xml.Serialization.XmlIgnore]
public IList<Theme> Themes { get { return _Themes; } set { _Themes = value; } }
private IList<Affinity> _Affinity = new List<Affinity>();
[IgnoreDataMember]
[System.Xml.Serialization.XmlIgnore]
public IList<Affinity> Affinity { get { return _Affinity; } set { _Affinity = value; } }
private IList<Word> _Words = new List<Word>();
[IgnoreDataMember]
[System.Xml.Serialization.XmlIgnore]
public IList<Word> Words { get { return _Words; } set { _Words = value; } }
}
using (global::NHibernate.ISession session = NHibernateApplication.GetCurrentSession())
{
global::NHibernate.ICriteria criteria = session.CreateCriteria(typeof(ThemingJob));
global::NHibernate.ICriteria countCriteria = session.CreateCriteria(typeof(ThemingJob));
criteria.AddOrder(global::NHibernate.Criterion.Order.Desc("Id"));
var qc = criteria.CreateCriteria("Query");
qc.SetFetchMode("Assets", global::NHibernate.FetchMode.Lazy);
qc.SetFetchMode("Themes", global::NHibernate.FetchMode.Lazy);
qc.SetFetchMode("Affinity", global::NHibernate.FetchMode.Lazy);
qc.SetFetchMode("Words", global::NHibernate.FetchMode.Lazy);
pageIndex = Convert.ToInt32(pageIndex) - 1; // convert to 0 based paging index
criteria.SetMaxResults(pageSize);
criteria.SetFirstResult(pageIndex * pageSize);
countCriteria.SetProjection(global::NHibernate.Criterion.Projections.RowCount());
int totalRecords = (int)countCriteria.List()[0];
return criteria.List<ThemingJob>().ToPagedList<ThemingJob>(pageIndex, pageSize, totalRecords);
}