XMLArray with different types but same element name and i:type attribute - xml-serialization

I am trying to serialize some data I have into this XML format but not able to achive the same.
The Desired XML output is below:
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Datas>
<Data xmlns="" i:type="DataA">
<Name>A1</Name>
<ADesc>Description for A</ADesc>
</Data>
<Data xmlns="" i:type="DataB">
<Name>B1</Name>
<BDesc>Description for b</BDesc>
</Data>
</Datas>
</Root>
The Classes I created for serialization are as follows:
public class Data
{
[XmlElement("Name")]
public string Name { get; set; }
}
public class DataA : Data
{
[XmlElement("ADesc")]
public string ADesc { get; set; }
}
public class DataB : Data
{
[XmlElement("BDesc")]
public string BDesc { get; set; }
}
[XmlRoot("Root")]
public class Root
{
[XmlArray("Datas")]
[XmlArrayItem(Type = typeof(Data))]
[XmlArrayItem(Type = typeof(DataA))]
[XmlArrayItem(Type = typeof(DataB))]
public List<Data> Datas { get; set; }
}
I use the below method for serializing:
internal static string Serialize(Root obj)
{
var ns = new XmlSerializerNamespaces();
ns.Add("i", "http://www.w3.org/2001/XMLSchema-instance");
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Root));
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, obj, ns);
return textWriter.ToString();
}
}
But the output I get is this (which is not correct):
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Datas>
<DataA>
<Name>A1</Name>
<ADesc>Description for A</ADesc>
</DataA>
<DataB>
<Name>B1</Name>
<BDesc>Description for b</BDesc>
</DataB>
</Datas>
</Root>

In order to generate the {http://www.w3.org/2001/XMLSchema-instance}type attribute using XmlSerializer, you need to attach [XmlInclude(typeof(XXX))] for all subclasses XXX of Data to a declared type somewhere in your object graph, i.e. on the Root class or the Data class itself:
//[XmlInclude(typeof(DataA))] /* Could also go here if you prefer. */
//[XmlInclude(typeof(DataB))] /* Could also go here if you prefer. */
public class Data
{
[XmlElement("Name")]
public string Name { get; set; }
}
public class DataA : Data
{
[XmlElement("ADesc")]
public string ADesc { get; set; }
}
public class DataB : Data
{
[XmlElement("BDesc")]
public string BDesc { get; set; }
}
[XmlRoot("Root")]
[XmlInclude(typeof(DataA))]
[XmlInclude(typeof(DataB))]
public class Root
{
[XmlArray("Datas")]
public List<Data> Datas { get; set; }
}
For more information, see Declaring Serialization Types in Troubleshooting Common Problems with the XmlSerializer and also Xsi:type Attribute Binding Support.

Related

Autofac - Configure Module List-Property with object

I want to configure per XML a module with a property, which contains a list of class MyObject.
My Module and MyObject class are looking like:
public class MyModule : Module
{
public IList<MyObject> MyObjects { get; set; }
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
// Do something with MyObjects.
}
}
public class MyObject
{
public string Id { get; set; }
public bool IsVisable { get; set; }
}
My assumption was to configure it like this in XML:
<modules name="MyModule">
<type>...</type>
<properties>
<MyObjects>
<MyObject>
<Id>1234</Id>
<IsVisilble>false</IsVisilble>
</MyObject>
</MyObjects>
</properties>
But if I run this, I get the following exception:
Unable to convert object of type 'Autofac.Configuration.Util.ConfiguredDictionaryParameter' to type 'System.Collections.Generic.IList`1[MyObject]'
I'm using Autofac 4.5.0 with Autofac.Configuration 4.0.1.
What am I doing wrong? Is there a way to get it working?

Entity Framework and DBContext data retrieval

I have a Web API where my repository class that has data hard-coded. I want to modify it to grab the same data from SQL Server database. I created the DB Context class in the DAL folder and a connection string in my web.config file with the same name as context class - MyClassesContext
public class myRepository
{
public myClasses.Type[] GetAllTypes()
{
return new myClasses.Type[]
{
new myClasses.Type
{
typeId="1",
typeVal = "New"
},
new myClasses.Type
{
typeId="2",
typeVal = "Old"
}
};
}
public myClasses.Employee[] GetAllEmployees()
{
return new myClasses.Employee[]
{
new myClasses.Employee
{
empId="111111",
empFName = "Jane",
empLName="Doe"
},
new myClasses.Employee
{
empId="222222",
empFName = "John",
empLName="Doe"
}
};
}
public bool VerifyEmployeeId(string id)
{
myClasses.Employee[] emp = new myClasses.Employee[]
{
new myClasses.Employee
{
empId="111111",
empFName = "Jane",
empLName="Doe"
},
new myClasses.Employee
{
empId="222222",
empFName = "John",
empLName="Doe"
}
};
for (var i = 0; i <= emp.Length - 1; i++)
{
if (emp[i].empId == id)
return true;
}
return false;
}
}
and my model class:
public class myClasses
{
public class Employee
{
public string empId { get; set; }
public string empFName { get; set; }
public string empLName { get; set; }
}
public class Type
{
public string typeId { get; set; }
public string typeVal { get; set; }
}
}
and here is my DBContext:
using System.Data.Entity;
using myClassesAPI.Models;
namespace myClassesAPI.DAL
{
public class myClassesContext : DbContext
{
public DbSet<myClasses.Employee> Employees { get; set; }
public DbSet<myClasses.Type> Types { get; set; }
}
}
Now the missing link here is how do I connect DBContext class. I did a great amount of googling but was not able to find anything relevant. Was wondering if anyone could point me in the right direction
Taking into consideration that everything is configured and working (Connection String, database access etc), in your repository, just make use of your DbContext class. Example to get a list of all Types:
public List<Type> GetAllTypes()
{
//Create an instance of your dbContext Class.
using (myClassesContext context = new myClassesContext ())
{
//Return all the Type's
return context.Type.ToList()
}
}
I think you need to read and study more about EntityFramework to get a good understanding on how things work, how you can query your database using LINQ. Here's a great starting point:
http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application
EDIT
I use this example of a connection string:
<add name="myClassesContext "
providerName="System.Data.SqlClient"
connectionString="Data Source=ServerName\InstanceName;Initial Catalog=DatabaseName;Integrated Security=True;MultipleActiveResultSets=True" />
Then, you set the same connection string name in your DbContext file:
public myClassesContext ()
: base(Connection.GetConnectionString("myClassesContext"))
{
}
How about using a connection string to the actual DB after specifying the database connection string to which you want to connect to:
public class myClassesContext : DbContext
{
public myClassesContext ()
: base("connection_string")
{
}
}
<configuration>
<connectionStrings>
<add name="connection_string"
providerName="..."
connectionString="..."/>
</connectionStrings>
</configuration>

How to access class properties using interface object which are not defined in the interface?

I am new to this forum. Now-days I am studying design patterns. I learnt about factory pattern and implemented simple example as shown below.
public interface IPlc
{
string Name { get; set; }
void Testping();
}
Public AbbPlc : IPlc
{
string Name { get; set; }
string slotnumber { get; set; }// Property relevant with this class
public void Testping()
{
console.writeline("ping executed successfully");
}
}
Public SiemensPlc : IPlc
{
string Name { get; set; }
string Racknumber { get; set; }// Property relevant with this class
public void Testping()
{
console.writeline("ping executed successfully");
}
}
//In Main Program
var objAbb = new IPlc() //Created object from interface
objAbb.Name = "46IC-PLC"; //Works OK
objAbb.slotnumber "3"; //Not works
var objSiemens = new IPlc() //Created object from interface
objSiemens.Name = "45IC-PLC"; //Works OK
objSiemens.Racknumber "5"; //Not works
Could you please tell me why these two methods doesn't work?
What I have to do to access properties from Interface object?
Do I need to use one more pattern with factory like decorator?

Using Generic Type DTO In ServiceStack Request

I was wondering if it's possible to use a Templated DTO requested of the type public class
RequestDTO<T, U> where T : class where U : class
{
public T ContextRequest { get; set; }
public U Request { get; set; }
}
And pass it to my service's request...
I've tried a simple example of type
public class MyContext
{
//removed some fields
public int IdUser {get;set;}
}
public class MyType1Request
{
public int IdRequest {get;set;}
}
public class MyType2Request
{
public DateTime SomeReallyImportantDate { get; set; }
}
public class UtenteService : Service
{
public UtenteService()
{
}
public string Any(RequestDTO<MyContext,MyType1Request> request)
{
return string.Format("User:{0} - IDRequest: {1}", request.ContextRequest.IdUser, request.Request.IDRequest);
}
public object Any(RequestDTO<MyContext, MyType2Request> request)
{
return string.Format("Utente:{0} - Data : {1}", request.ContextRequest.IDUtente, request.Request.DataLavorativa);
}
But I got this as far I try to access to the service
Sequence contains more than one matching element
Another solution is to implement in each my DTO Request object a IContext (and maybe IContextExt IContextSpecificManner) into the request object...but I would prefer to use the first approach
Thanks
AFAIK - This should work. The only thing that I am missing here is, you need to register route in apphost like:
Routes.Add>("/Utente/{IdUser}/{IdRequest}")

deserialize existing xml into custom object

I have the following xml:
<state>
<groups>
<group id='1' name='Basic Search Options'>
<control name='Building' label='In' display='true' configurable='false'/>
<control name='SearchType' label='For' display='true' configurable='false'/>
<control id='1' default='C' name='Search By' label='By'>
<option searchtype='C' searchmode='Cnumber' value='CNumber' label='C Number' display='true'/>
<option searchtype='C' searchmode='crossrefnumber' value='CNumber1' label='Cross Reference Number' display='true'/>
<option searchtype='P' searchmode='' value='CaseNumber' label='P Name' display='true'/>
<option searchtype='P' searchmode='' value='CaseNumber' label='A Name' display='false'/>
</control>
</group>
<group id='2' name='Advanced Search Options'>
<control name='Ctatus' label='C Status' display='true'/>
<control name='DateFiled' label='Date Filed' display='true'/>
</group>
</groups>
How would I de-serialize this into the following object? I dont want my xml to have the following tags "ArrayofGroup", instead the xml should have custom tags like mention above.
public class GroupOfControls
{
public int instanceId { get; set; }
public int GroupId { get; set; }
public string Name { get; set; }
public List<SearchControl> Group { get; set; }
}
public class SearchControl
{
public string Name { get; set; }
public string Label { get; set; }
public bool Display { get; set; }
public string Default { get; set; }
public List<SearchOption> SearchOptions { get; set; }
}
public class SearchOption
{
public string Value { get; set; }
public string Label { get; set; }
public bool Display { get; set; }
public string SearchMode { get; set; }
public string SearchType { get; set; }
}
}
If you don't have an XSD file, you need to create one from your XML. You can do this with the Visual Studio Command Line using the following command:
xsd myfilename.xml
Once you have an XSD file this should be easy enough.
I am working with Visual Studio 2010 (C#/.Net 4) and I would do this:
First I would make a new solution in Visual Studio:
Then you need to import the XSD file into your project by right clicking on your solution, and selecting Add => Existing Item and browsing to the XSD.
Once you have the XSD inside your project you need to launch the Visual Studio command prompt, use cd to navigate to your projects directory and then type the following command:
xsd myFilename.xsd /classes
This generates the C# class you are going to deserialize your XML into. Use the Add Existing Item dialogue to import this new class into your solution.
Next you add using System.Xml.Serialization; and using System.IO; to your using statements. Then use the following code to deserialize your XML to an object (assuming the XML validates against your XSD). The most recent XSD I could file I called ResponseData as shown below:
With this in mind, my C# code is below:
using System;
using System.IO;
using System.Xml.Serialization;
namespace XML_Deserialization
{
class Program
{
static void Main(string[] args)
{
ResponseData myResponseData = new ResponseData();
XmlSerializer mySerializer = new XmlSerializer(typeof(ResponseData));
StreamReader myStreamReader = new StreamReader(#"C:\Users\JMK\Documents\Visual Studio 2010\Projects\scratch\XML Deserialization\XML Deserialization\text.xml");
myResponseData = (ResponseData)mySerializer.Deserialize(myStreamReader);
Console.ReadLine();
}
}
}