How hashtable is working in WCF? - wcf

I have a question.
Consider the below
IService1.cs
[ServiceContract]
public interface IService1
{
[OperationContract]
Hashtable GetHashTableCollection();
[OperationContract]
List<A> GetARecords();
}
[DataContract]
public class A
{
[DataMember]
public int MyProperty { get; set; }
[DataMember]
public Hashtable MyTable { get; set; }
}
Service1.cs
public class Service1 : IService1
{
public Hashtable GetHashTableCollection()
{
Hashtable hashtable = new Hashtable();
hashtable.Add("Area", 1000);
hashtable.Add("Perimeter", 55);
hashtable.Add("Mortgage", 540);
return hashtable;
}
public List<A> GetARecords()
{
List<A> Alist = new List<A>();
Alist.Add(new A { MyProperty = 1, MyTable = GetHashTableCollection() });
Alist.Add(new A { MyProperty = 2, MyTable = GetHashTableCollection() });
return Alist;
}
}
And the client Application is as under
private void button1_Click(object sender, EventArgs e)
{
ServiceReference1.Service1Client sc = new ServiceReference1.Service1Client();
var r1 = sc.GetHashTableCollection();
var r2 = sc.GetARecords();
}
It is working fine without any problem. The HashTable has been converted to Dictionary object.
I was under the impression that since HashTable uses IDictionary, so it should fail at compile time(happened in 3.5).
Cannot implicitly convert type 'System.Collections.Generic.Dictionary' to 'System.Collections.Hashtable'
However, it worked. How?
Am I missing any basic concept? Or DataContractSerializer is doing the work? Or something has changed in dot.net 4.0?
What it is and why it is working?

It's based on IDictionary. WCF treats IDictionary as a Dictionary<object, object> and it's exposed as such on the WSDL. You could have a custom class which implemented IDictionary, and the behavior would be the same. For example, if you run either of the projects below, and use svcutil or Add Service Reference to generate a proxy to the service, where you had an IDictionary type, you'll get a Dictionary<object, object> in the client instead.
public class StackOverflow_15471185
{
[ServiceContract]
public interface IService1
{
[OperationContract]
Hashtable GetHashTableCollection();
[OperationContract]
List<A> GetARecords();
}
[DataContract]
public class A
{
[DataMember]
public int MyProperty { get; set; }
[DataMember]
public Hashtable MyTable { get; set; }
}
public class Service : IService1
{
public Hashtable GetHashTableCollection()
{
Hashtable hashtable = new Hashtable();
hashtable.Add("Area", 1000);
hashtable.Add("Perimeter", 55);
hashtable.Add("Mortgage", 540);
return hashtable;
}
public List<A> GetARecords()
{
List<A> Alist = new List<A>();
Alist.Add(new A { MyProperty = 1, MyTable = GetHashTableCollection() });
Alist.Add(new A { MyProperty = 2, MyTable = GetHashTableCollection() });
return Alist;
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "");
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
host.Open();
Console.WriteLine("Host opened");
var factory = new ChannelFactory<IService1>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
var proxy = factory.CreateChannel();
Console.WriteLine(proxy.GetHashTableCollection());
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
public class StackOverflow_15471185_b
{
[ServiceContract]
public interface IService1
{
[OperationContract]
MyDic GetHashTableCollection();
[OperationContract]
List<A> GetARecords();
}
public class MyDic : IDictionary
{
public IDictionary dic = new Hashtable();
public void Add(object key, object value)
{
dic.Add(key, value);
}
public void Clear()
{
dic.Clear();
}
public bool Contains(object key)
{
return dic.Contains(key);
}
public IDictionaryEnumerator GetEnumerator()
{
return dic.GetEnumerator();
}
public bool IsFixedSize
{
get { return dic.IsFixedSize; }
}
public bool IsReadOnly
{
get { return dic.IsReadOnly; }
}
public ICollection Keys
{
get { return dic.Keys; }
}
public void Remove(object key)
{
dic.Remove(key);
}
public ICollection Values
{
get { return dic.Values; }
}
public object this[object key]
{
get
{
return dic[key];
}
set
{
dic[key] = value;
}
}
public void CopyTo(Array array, int index)
{
dic.CopyTo(array, index);
}
public int Count
{
get { return dic.Count; }
}
public bool IsSynchronized
{
get { return dic.IsSynchronized; }
}
public object SyncRoot
{
get { return dic.SyncRoot; }
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)dic).GetEnumerator();
}
}
[DataContract]
public class A
{
[DataMember]
public int MyProperty { get; set; }
[DataMember]
public MyDic MyTable { get; set; }
}
public class Service : IService1
{
public MyDic GetHashTableCollection()
{
MyDic hashtable = new MyDic();
hashtable.Add("Area", 1000);
hashtable.Add("Perimeter", 55);
hashtable.Add("Mortgage", 540);
return hashtable;
}
public List<A> GetARecords()
{
List<A> Alist = new List<A>();
Alist.Add(new A { MyProperty = 1, MyTable = GetHashTableCollection() });
Alist.Add(new A { MyProperty = 2, MyTable = GetHashTableCollection() });
return Alist;
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "");
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
host.Open();
Console.WriteLine("Host opened");
var factory = new ChannelFactory<IService1>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
var proxy = factory.CreateChannel();
Console.WriteLine(proxy.GetHashTableCollection());
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}

Related

Get session value in parameterless constructor in ASP .NET Core

I have a class with a parameterless constructor and I am wondering how to get a value from the session. I have tried dependency injection but since I am using this class for deserialization, the httpcontextaccessor is always null.
public class Category
{
public Category()
{
_language = "french"; <-- how to get value from session
}
private string _Name;
public string Name {
get {
if (!string.IsNullOrEmpty(_language))
{
var dict = new Dictionary<string, string>();
this.localization.FirstOrDefault(x => x.TryGetValue(_language, out dict));
return dict != null && dict.ContainsKey("name") ? dict["name"] : _Name;
}
else
return _Name;
}
set
{
_Name = value;
}
}
public List<Dictionary<string, Dictionary<string, string>>> localization { get; set; }
}
You can get session value in custom model like below:
public class Category
{
private readonly ISession _session; //add this..
public Category(ISession session)
{
_session = session;
_language = _session.GetString("language");
}
private string? _language;
private string _Name;
public string Name {
get {
if (!string.IsNullOrEmpty(_language))
{
var dict = new Dictionary<string, string>();
this.localization.FirstOrDefault(x => x.TryGetValue(_language, out dict));
return dict != null && dict.ContainsKey("name") ? dict["name"] : _Name;
}
else
return _Name;
}
set
{
_Name = value;
}
}
public List<Dictionary<string, Dictionary<string, string>>> localization { get; set; }
}
Test it in Controller:
public IActionResult Index()
{
HttpContext.Session.SetString("language", "en-US");
var model = new CategoryModel(HttpContext.Session);
return View();
}
Be sure add AddSession and UseSession middleware in Program.cs or in Startup.cs.
Reference: Configure session state
but since I am using this class for deserialization, the httpcontextaccessor is always null.
A simple demo you could follow:
Model:
public class CategoryModel
{
private readonly IHttpContextAccessor _contextAccessor;
public CategoryModel(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
_language = contextAccessor.HttpContext.Session.GetString("language");
}
//........
}
Test in Controller:
public class HomeController : Controller
{
private readonly IHttpContextAccessor _contextAccessor;
public HomeController(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public IActionResult Index()
{
HttpContext.Session.SetString("language", "en-US");
var model = new CategoryModel(_contextAccessor);
return View();
}
}
Register the service like:
//.....
builder.Services.AddSession();
builder.Services.AddHttpContextAccessor();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseRouting();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
So I created a static class:
public static class AppContext
{
public static IHttpContextAccessor HttpContextAccessor { get; set; }
public static void Configure(IHttpContextAccessor accessor)
{
HttpContextAccessor = accessor;
}
}
And then in the class where I couldn't do dependency injection, I was able to get the session:
public Category()
{
_language = AppContext.HttpContextAccessor.HttpContext.Session.GetString("language");
}
Had to add this to Configure in Startup:
AppContext.Configure(context);

How to implement growing object with a design pattern?

I want to design a response and design it by responses in my asp.net core application. The simlpe response is like following.
public class Response {
public string Status { get; set; } => "Ok";
public BaseReport BaseReport { get;set;}
}
if user sends extra parameters to my service, I want to change my response content dynamically.
public class ReportsController : ControllerBase
{
[HttpGet]
public ActionResult<Response> GetReport(bool isEmployee, bool isFinanace, bool isInformatinTech)
{
// if all parameters fals, return base report.
var report = baseReposrService.Get();
var response = new Response() { BaseReport = report };
if(isEmployee)
{
var ereport = employeeService.Get();
var response = new Response() {
BaseReport = report,
EmployeeReport = ereport
};
}
if(isFinanace)
{
var freport = financeService.Get();
var response = new Response() {
BaseReport = report,
EmployeeReport = freport
};
}
...
...
}
}
the response object is growing by query parameters.
So, is implementing the decorator pattern for this problem right way? Is there any best practice for these type problems?
I tried as below:
public class Response
{
public Response()
{
BaseReport = new BaseReport();
}
public string Status { get; set; } ="Ok";
public BaseReport BaseReport { get; set; }
}
public class BaseReport
{
public string report { get; set; }
public string reportcontent { get; set; }
}
public interface IResponseFactory
{
IResponseFactory Add(string key);
Response Create(string key);
}
public class ResponseFactory1 : IResponseFactory
{
private readonly Dictionary<string, Response> _responsedic = new Dictionary<string, Response>();
public ResponseFactory1()
{
this.Add("Employee").Add("Finanace").Add("InformatinTech");
}
public IResponseFactory Add(string key)
{
var response = new Response();
response.BaseReport.report = key;
response.BaseReport.reportcontent = key + "content";
_responsedic.Add(key, response);
return this;
}
public Response Create(string responsename)
{
if (_responsedic.ContainsKey(responsename))
{
return _responsedic[responsename];
}
else
{
return new Response() { BaseReport = new BaseReport() { report = "basereport",reportcontent= "basereportcontent" } };
}
}
in startup class:
services.AddSingleton<IResponseFactory, ResponseFactory1>();
in controller:
[HttpGet]
public ActionResult<Response> GetReport(string responsetype)
{
var response = _responseFactory.Create(responsetype);
return response;
}

WCF SOAP service give an error An error occurred while receiving the HTTP response to http://localhost/Service1.svc

when i make the client and call the getNews it goes into service but after the return its give me this error
System.ServiceModel.CommunicationException: 'An error occurred while receiving the HTTP response to http://localhost/Service1.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.'
Interface is :
[ServiceContract , XmlSerializerFormat]
public interface IService1
{
[OperationContract]
// string getNews(getNewsRequest request);
// GetNewsOutputStructure getNews (getNewsRequest request);
// getNewsResponseStructure getNews(getNewsRequest request);
getNewsResponse getNews();
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
// TODO: Add your service operations here
}
the implementation is
public getNewsResponse getNews()
{
getNewsResponse response = null;
List<NewsListStructure> newsList = new List<NewsListStructure>();
NewsStructure news = null;
for (int i = 0; i < 2; i++)
{
news = new NewsStructure();
news.NewsText = "Test";
news.NewsId = "22";
news.NewsDate = DateTime.Now;
MediaExtentionsArrayStructure[] mediaExtentionsArrayStructures = null;
news.MediaExtentionsArrayObject = mediaExtentionsArrayStructures; //nnList[i].NewsDate;
news.NewsClassificationObject = new NewsClassificationStructure { NewsClassificationId = 1.ToString(), NewsClassificationDescription = "g" };
// news.MediaArrayObject = nnList[i].NewsDate;
NewsListStructure newsStructure = new NewsListStructure();
newsStructure.NewsObject = news;
newsList.Add(newsStructure);
}
// return newsList;
GetNewsOutputStructure getNewsOutputStructure = new GetNewsOutputStructure();
getNewsOutputStructure.NewsListObject = newsList.ToArray();
getNewsOutputStructure.ResponseStatus = ResponseStatusType.Success;
getNewsOutputStructure.DataSchemaVersion = 1;
getNewsOutputStructure.FaildReasonListObject = new FaildReasonListStructure[1] ;
var fdf = new ErrorStructure() { Item = "hh" , ItemElementName = ItemChoiceType.ErrorMessage};
getNewsOutputStructure.FaildReasonListObject[0] = new FaildReasonListStructure();
getNewsOutputStructure.FaildReasonListObject[0].Item = fdf;
// return getNewsOutputStructure;
getNewsResponseStructure getNewsResponseStructure = new getNewsResponseStructure();
getNewsResponseStructure.Item = getNewsOutputStructure;
// return getNewsResponseStructure;
// response = new getNewsResponse(getNewsResponseStructure);
response = new getNewsResponse();
response.getNewsResponseObject = getNewsResponseStructure;
response.getNewsResponseObject.Item = newsList;
return response;
}
after return response i got an error
and this is the object i will return
[DataContract]
public class getNewsResponse
{
// [System.ServiceModel.MessageBodyMemberAttribute()]
[XmlElement]
[DataMember]
public getNewsResponseStructure getNewsResponseObject;
public getNewsResponse()
{
}
public getNewsResponse(getNewsResponseStructure getNewsResponseObject)
{
this.getNewsResponseObject = getNewsResponseObject;
}
}
[DataContract]
public class getNewsResponseStructure
{
// [DataMember]
private object itemField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("getNewsResponseDetailObject", typeof(GetNewsOutputStructure))]
// [System.Xml.Serialization.XmlElementAttribute("ServiceError", typeof(CommonErrorStructure))]
[XmlElement]
[DataMember]
public object Item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
}
[DataContract]
public partial class GetNewsOutputStructure
{
private ResponseStatusType responseStatusField;
private NewsListStructure[] newsListObjectField;
private FaildReasonListStructure[] faildReasonListObjectField;
private decimal dataSchemaVersionField;
// [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
[XmlElement]
/// <remarks/>
[DataMember]
public ResponseStatusType ResponseStatus
{
get
{
return this.responseStatusField;
}
set
{
this.responseStatusField = value;
}
}
[XmlElement]
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute("NewsListObject", Order = 1)]
[DataMember]
public NewsListStructure[] NewsListObject
{
get
{
return this.newsListObjectField;
}
set
{
this.newsListObjectField = value;
}
}
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute("FaildReasonListObject", Order = 2)]
[DataMember]
[XmlElement]
public FaildReasonListStructure[] FaildReasonListObject
{
get
{
return this.faildReasonListObjectField;
}
set
{
this.faildReasonListObjectField = value;
}
}
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute(Order = 3)]
[DataMember]
[XmlElement]
public decimal DataSchemaVersion
{
get
{
return this.dataSchemaVersionField;
}
set
{
this.dataSchemaVersionField = value;
}
}
}
[DataContract]
[Flags]
public enum ResponseStatusType
{
// [System.Runtime.Serialization.EnumMemberAttribute()]
[EnumMember]
/// <remarks/>
Success,
// [System.Runtime.Serialization.EnumMemberAttribute()]
[EnumMember]
/// <remarks/>
Fail,
}
[DataContract]
public partial class NewsListStructure
{
private NewsStructure newsObjectField;
[DataMember]
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
[XmlElement]
public NewsStructure NewsObject
{
get
{
return this.newsObjectField;
}
set
{
this.newsObjectField = value;
}
}
}
[DataContract]
public partial class FaildReasonListStructure
{
private ErrorStructure itemField;
[DataMember]
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute("ErrorObject", Order = 0)]
[XmlElement]
public ErrorStructure Item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
}
[DataContract]
public partial class ErrorStructure
{
private string itemField;
private ItemChoiceType itemElementNameField;
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute("ErrorCode", typeof(string), Order = 0)]
// [System.Xml.Serialization.XmlElementAttribute("ErrorMessage", typeof(string), Order = 0)]
// [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")]
[DataMember]
[XmlElement]
public string Item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute(Order = 1)]
// [System.Xml.Serialization.XmlIgnoreAttribute()]
[XmlElement]
public ItemChoiceType ItemElementName
{
get
{
return this.itemElementNameField;
}
set
{
this.itemElementNameField = value;
}
}
}
[DataContract]
[Flags]
public enum ItemChoiceType
{
// [System.Runtime.Serialization.EnumMemberAttribute()]
[EnumMember]
/// <remarks/>
ErrorCode,
// [System.Runtime.Serialization.EnumMemberAttribute()]
[EnumMember]
/// <remarks/>
ErrorMessage,
}
[DataContract]
public partial class NewsStructure
{
private string newsIdField;
private NewsClassificationStructure newsClassificationObjectField;
private string newsTextField;
private MediaArrayStructure[] mediaArrayObjectField;
private MediaExtentionsArrayStructure[] mediaExtentionsArrayObjectField;
private System.DateTime newsDateField;
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
[DataMember]
[XmlElement]
public string NewsId
{
get
{
return this.newsIdField;
}
set
{
this.newsIdField = value;
}
}
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute(Order = 1)]
[DataMember]
[XmlElement]
public NewsClassificationStructure NewsClassificationObject
{
get
{
return this.newsClassificationObjectField;
}
set
{
this.newsClassificationObjectField = value;
}
}
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute(Order = 2)]
[DataMember]
[XmlElement]
public string NewsText
{
get
{
return this.newsTextField;
}
set
{
this.newsTextField = value;
}
}
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute("MediaArrayObject", Order = 3)]
[DataMember]
[XmlElement]
public MediaArrayStructure[] MediaArrayObject
{
get
{
return this.mediaArrayObjectField;
}
set
{
this.mediaArrayObjectField = value;
}
}
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute("MediaExtentionsArrayObject", Order = 4)]
[DataMember]
[XmlElement]
public MediaExtentionsArrayStructure[] MediaExtentionsArrayObject
{
get
{
return this.mediaExtentionsArrayObjectField;
}
set
{
this.mediaExtentionsArrayObjectField = value;
}
}
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute(DataType = "date", Order = 5)]
[DataMember]
[XmlElement]
public System.DateTime NewsDate
{
get
{
return this.newsDateField;
}
set
{
this.newsDateField = value;
}
}
}
[DataContract]
public partial class MediaExtentionsArrayStructure
{
private string itemField;
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute("MediaExtentions", Order = 0)]
[DataMember]
[XmlElement]
public string Item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
}
[DataContract]
public partial class MediaArrayStructure
{
private byte[] itemField;
[DataMember]
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute("Media", DataType = "base64Binary", Order = 0)]
[XmlElement]
public byte[] Item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
}
[DataContract]
public partial class NewsClassificationStructure
{
private string newsClassificationIdField;
private string newsClassificationDescriptionField;
[DataMember]
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
[XmlElement]
public string NewsClassificationId
{
get
{
return this.newsClassificationIdField;
}
set
{
this.newsClassificationIdField = value;
}
}
[DataMember]
/// <remarks/>
// [System.Xml.Serialization.XmlElementAttribute(Order = 1)]
[XmlElement]
public string NewsClassificationDescription
{
get
{
return this.newsClassificationDescriptionField;
}
set
{
this.newsClassificationDescriptionField = value;
}
}
}
//[System.Diagnostics.DebuggerStepThroughAttribute()]
//[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
//[System.Xml.Serialization.XmlSchemaProviderAttribute("ExportSchema")]
//[System.Xml.Serialization.XmlRootAttribute]
[DataContract]
public partial class CommonErrorStructure : object, System.Xml.Serialization.IXmlSerializable
{
private System.Xml.XmlNode[] nodesField;
private static System.Xml.XmlQualifiedName typeName = new System.Xml.XmlQualifiedName();
[DataMember]
[XmlElement]
public System.Xml.XmlNode[] Nodes
{
get
{
return this.nodesField;
}
set
{
this.nodesField = value;
}
}
public void ReadXml(System.Xml.XmlReader reader)
{
this.nodesField = System.Runtime.Serialization.XmlSerializableServices.ReadNodes(reader);
}
public void WriteXml(System.Xml.XmlWriter writer)
{
System.Runtime.Serialization.XmlSerializableServices.WriteNodes(writer, this.Nodes);
}
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public static System.Xml.XmlQualifiedName ExportSchema(System.Xml.Schema.XmlSchemaSet schemas)
{
System.Runtime.Serialization.XmlSerializableServices.AddDefaultSchema(schemas, typeName);
return typeName;
}
}
client code is
ServiceReference2.Service1Client client = new ServiceReference2.Service1Client();
ServiceReference2.getNewsRequest k = new ServiceReference2.getNewsRequest();
k.getNewsRequestObject = new ServiceReference2.GetNewsRequestStructure();
k.getNewsRequestObject.LastReceivedNewsItemId = "10000";
k.getNewsRequestObject.NumberOfRequestedNews = "5";
k.getNewsRequestObject.ServiceToken = "";
k.getNewsRequestObject.SPAGovernmentSectorKey = "";
k.getNewsRequestObject.SubServiceObject = new ServiceReference2.SubServicesStructure { SubServiceId = "1", SubServiceDescription = "desc" };
k.getNewsRequestObject.TypeOfData = ServiceReference2.TypeOfDataType.All;
k.yefiSOAPHeaderElement = new ServiceReference2.YefiHeader();
k.yefiSOAPHeaderElement.ServiceID = "1";
k.yefiSOAPHeaderElement.SourceID = "2";
k.yefiSOAPHeaderElement.SourceName = "genral";
var t = client.getNews( k);
// Always close the client.
client.Close();
This is because you pass List<NewsListStructure> to response.getNewsResponseObject.Item. According to the definition of your class, response.getNewsResponseObject.Item can only accept Object type, not List<Object> type.
There are two solutions. The first is to modify the getNewsResponseStructure class, as shown below:
public class getNewsResponseStructure
{
// [DataMember]
private List<Object> itemField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("getNewsResponseDetailObject", typeof(GetNewsOutputStructure))]
// [System.Xml.Serialization.XmlElementAttribute("ServiceError", typeof(CommonErrorStructure))]
[XmlElement]
[DataMember]
public List<Object> Item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
}
The second is to create NewsListStructure and pass it to response.getNewsResponseObject.Item:
NewsListStructure news = new NewsListStructure();
response.getNewsResponseObject.Item = news;
the problem was in my Client i tried to sent a diffrent type of object that i cast it in the service
this the wrong
response.getNewsResponseObject.Item = newsList;
this is true
response.getNewsResponseObject.Item = getNewsOutputStructure;
becouse in service i told it i will sent to you an
GetNewsOutputStructure object not List<NewsListObject>
in service
[System.Xml.Serialization.XmlElementAttribute("getNewsResponseDetailObject", typeof(GetNewsOutputStructure), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]

How to return a list of a defined type WCF service

I have defined the data contract as follows:
[DataContract]
public class TestResult
{
[DataMember]
public string[] NegResponses { get; set; }
[DataMember]
public bool Pass { get; set; }
[DataMember]
public string Request { get; set; }
[DataMember]
public string Response { get; set; }
}
Is it possible to return a list of the above type in the operation contract as follows:
[OperationContract]
[FaultContract(typeof(TestFault))]
List<TestResult> Tester(string nodeCaption);
And what else I have to look into to return a list of a type that has been defined ?
By the way I guess I am not using svcutil and instead using channel factory as follows:
private static readonly ITestService TestClient;
// initialize a channel factory
var channelFactory = new ChannelFactory<ITestService>(new NetTcpBinding(SecurityMode.None), endPoint);
// Create a channel
TestClient = channelFactory.CreateChannel();
The client-side and the server-side should share the same service contract and data contract. This is fundamental that we could consume the service on the client-side.
Here is an example, wish it is useful to you.
Server-side.
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:21011");
BasicHttpBinding binding = new BasicHttpBinding();
using (ServiceHost sh = new ServiceHost(typeof(MyService), uri))
{
sh.AddServiceEndpoint(typeof(IService), binding, "");
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior()
{
HttpGetEnabled=true
};
sh.Description.Behaviors.Add(smb);
}
Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
sh.Opened += delegate
{
Console.WriteLine("Service is ready");
};
sh.Closed += delegate
{
Console.WriteLine("Service is clsoed");
};
sh.Open();
Console.ReadLine();
//pause
sh.Close();
Console.ReadLine();
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
List<Product> SayHello();
}
public class MyService : IService
{
public List<Product> SayHello()
{
return new List<Product>()
{
new Product()
{
ID=1,
Name="Apple"
},
new Product()
{
ID=2,
Name="Pear"
}
};
}
}
[DataContract(Namespace = "MyNamespace")]
public class Product
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
}
Client-side (Console application,we call the service with ChannelFactory).
class Program
{
static void Main(string[] args)
{
BasicHttpBinding binding = new BasicHttpBinding();
Uri uri = new Uri("http://10.157.13.69:21011");
ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri));
IService service = factory.CreateChannel();
try
{
var result = service.SayHello();
foreach (var item in result)
{
Console.WriteLine($"ID:{item.ID}\n,Name:{item.Name}");
}
}
catch (Exception)
{
throw;
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
List<Product> SayHello();
}
[DataContract(Namespace = "MyNamespace")]
public class Product
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
}
Data Contract should be decorated with Namespace property, this will guarantee that the serialization and deserialization process properly). Actually, the service contract also needs a namespace to represent the practical method name, which will be used to addressing the method on the server-side. but there is a default value in the namespace.
http://tempuri.org
Feel free to let me know if there is anything I can help with.

XML Serialization - Is it possible to serialize a model in this way?

I have the following model:
public class ABaseObject
{
private Guid id = Guid.NewGuid();
public ABaseObject()
{
}
public Guid ID { get { return id; } }
}
public class ADerivedObject : ABaseObject
{
public ADerivedObject()
{
}
public string Name { get; set; }
}
public class AObjectCollection<T>
{
private List<T> items = new List<T>();
public AObjectCollection()
{
}
public IEnumerable<T> Items { get { return items; } }
public void Add(T item)
{
items.Add(item);
}
public void Save(string filePath)
{
FileStream writer = new FileStream(filePath, FileMode.Create);
DataContractSerializer s = new DataContractSerializer(typeof(T));
s.WriteObject(writer, this);
writer.Close();
}
public void Load(string filePath)
{
FileStream fs = new FileStream(filePath, FileMode.Open);
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(T));
// Deserialize the data and read it from the instance.
T deserializedObj = (T)ser.ReadObject(reader, true);
reader.Close();
fs.Close();
}
}
So basically I want to be able to do the following:
var der = new ADerivedObject();
der.Name = "Test";
var col = new AObjectCollection<ADerivedObject>();
col.Add(der);
col.Save("C:\MyCollection.xml");
...
var col2 = new AObjectCollection<ADerivedObject>();
col2.Load("C:\MyCollection.xml");
When serialized it should look something like:
<Collection>
<Item>
<ID></ID>
<Name></Name>
</Item>
</Collection>
I have played around with DataContracts and XmlSerializer but I can't quite seem to find a way to do it.
This code:
public class ABaseObject
{
public ABaseObject() { }
public Guid ID { get; set;}
}
[XmlType("Item")]
public class ADerivedObject : ABaseObject
{
public ADerivedObject() {}
public string Name { get; set; }
}
[XmlType("Collection")]
public class AObjectCollection<T>
{
private System.Xml.Serialization.XmlSerializerNamespaces ns;
private System.Xml.Serialization.XmlSerializer s;
public AObjectCollection()
{
ns= new System.Xml.Serialization.XmlSerializerNamespaces();
ns.Add( "", "");
s= new System.Xml.Serialization.XmlSerializer(this.GetType());
Items = new List<T>();
}
public List<T> Items { get; set; }
public DateTime LastSaved { get;set; }
public void Add(T item)
{
Items.Add(item);
}
public void Save(string filePath)
{
LastSaved= System.DateTime.Now;
var xmlws = new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
using ( var writer = System.Xml.XmlWriter.Create(filePath, xmlws))
{
s.Serialize(writer, this, ns);
}
}
public static AObjectCollection<T2> Load<T2>(string filepath)
{
AObjectCollection<T2> obj;
try
{
var s= new System.Xml.Serialization.XmlSerializer(typeof(AObjectCollection<T2>));
using(System.IO.StreamReader reader= System.IO.File.OpenText(filepath))
{
obj= (AObjectCollection<T2>) s.Deserialize(reader);
}
}
catch
{
obj= new AObjectCollection<T2>();
}
return obj;
}
}
produces this output:
<Collection>
<Items>
<Item>
<ID>00000000-0000-0000-0000-000000000000</ID>
<Name>Test</Name>
</Item>
</Items>
<LastSaved>2010-02-04T07:32:05.812-05:00</LastSaved>
</Collection>
There are ways to tweak the XML to remove the Collection/Items layer. Search SO for other Collection / Serialization questions.