Deserialize wcf xml response using datacontractserializer C# - datacontractserializer

In our project, we are getting response from wcf service in xml format which we want to deserialize using datacontract serializer.
Below is the xml response.
<ArrayOfCustomerData xmlns="http://schemas.datacontract.org/2004/07/PACRM.QCT">
<CustomerData>
<AccountID>String content</AccountID>
<AccountName1>String content</AccountName1>
</CustomerData>
<CustomerData>
<AccountID>String content</AccountID>
<AccountName1>String content</AccountName1>
</CustomerData>
</ArrayOfCustomerData>
We have written the following DataContract class to deserialize the xml.
[DataContract]
public class ArrayOfCustomerData
{
[DataMember(Name="CustomerData")]
public CustomerData[] customerData { get; set; }
}
[DataContract]
public class CustomerData
{
[DataMember(IsRequired = true, Name = "AccountID")]
public string new_AccountID { get; set; }
[DataMember(IsRequired = true, Name = "AccountName1")]
public string new_accountname1 { get; set; }
}
C# code for deserialization is given below.
DataContractSerializer dcs = new DataContractSerializer(typeof(ArrayOfCustomerData));
ArrayOfCustomerData data=new ArrayOfCustomerData();
using (var stream = new StreamReader(response.GetResponseStream()))
{
var text=stream.ReadToEnd();
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(text));
XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateTextWriter(ms, Encoding.UTF8);
dcs.WriteObject(xdw, data);
}
when i check the data.cusotmerData, it is returning null.
Can anyone please provide solution for this issue? Thanks!

You don't need the class ArrayOfCustomerData - that is just adding an unecessary extra element to the expected XML. You can use CustomerData[], as the type passed to the DataContractSerializer constructor, as shown below:
public class StackOverflow_24673714
{
const string XML = #"<ArrayOfCustomerData xmlns=""http://schemas.datacontract.org/2004/07/PACRM.QCT"">
<CustomerData>
<AccountID>String content ID 1</AccountID>
<AccountName1>String content name 1</AccountName1>
</CustomerData>
<CustomerData>
<AccountID>String content ID 2</AccountID>
<AccountName1>String content name 2</AccountName1>
</CustomerData>
</ArrayOfCustomerData>";
[DataContract(Name = "CustomerData", Namespace = "http://schemas.datacontract.org/2004/07/PACRM.QCT")]
public class CustomerData
{
[DataMember(IsRequired = true, Name = "AccountID")]
public string new_AccountID { get; set; }
[DataMember(IsRequired = true, Name = "AccountName1")]
public string new_accountname1 { get; set; }
}
public static void Test()
{
var ms = new MemoryStream();
var ws = new XmlWriterSettings { Indent = true, IndentChars = " ", OmitXmlDeclaration = true, Encoding = Encoding.UTF8 };
var w = XmlWriter.Create(ms, ws);
var dcs = new DataContractSerializer(typeof(CustomerData[]));
var obj = new CustomerData[] {
new CustomerData { new_AccountID = "String content 1", new_accountname1 = "String content 2" },
new CustomerData { new_AccountID = "String content 3", new_accountname1 = "String content 4" }
};
dcs.WriteObject(w, obj);
w.Flush();
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms = new MemoryStream(Encoding.UTF8.GetBytes(XML));
var cds = (CustomerData[])dcs.ReadObject(ms);
Console.WriteLine(cds.Length);
foreach (var cd in cds)
{
Console.WriteLine(" {0} - {1}", cd.new_AccountID, cd.new_accountname1);
}
}
}

Related

List<DateTime> Post call issue

I'm trying to do a JSON post call using a List property (RecurrenceException) but once the AddAppointment() method is called, RecurrenceException will always be null as its supposed to be but I get this exception on my API controller:
Microsoft.Data.SqlClient.SqlException: 'The parameterized query '(#PK int,#Title nvarchar(8),#Description nvarchar(8),#StartDate ' expects the parameter '#RecurrenceException', which was not supplied.'
Below is my client Razor Page code:
async Task AddAppointment(SchedulerCreateEventArgs e)
{
UvwHolidayPlanner holidayPlannerItem = e.Item as UvwHolidayPlanner;
List<DateTime> lst = new List<DateTime>();
holidayPlanner.Pk = holidayPlannerItem.Pk;
holidayPlanner.Title = holidayPlannerItem.Title;
holidayPlanner.Description = holidayPlannerItem.Description;
holidayPlanner.StartDate = holidayPlannerItem.StartDate;
holidayPlanner.EndDate = holidayPlannerItem.EndDate;
holidayPlanner.IsAllDay = holidayPlannerItem.IsAllDay;
if (holidayPlannerItem.RecurrenceRule == null)
{
holidayPlanner.RecurrenceRule = " ";
}
else
{
holidayPlanner.RecurrenceRule = holidayPlannerItem.RecurrenceRule;
}
holidayPlanner.RecurrenceException = holidayPlannerItem.RecurrenceException;
holidayPlanner.RecurrenceId = holidayPlannerItem.RecurrenceId;
await http.CreateClient("ClientSettings").PostAsJsonAsync<UvwHolidayPlanner>($"{_URL}/api/HolidayPlannerOperations/HolidayPlanner", holidayPlanner);
HolidayPlanners = (await http.CreateClient("ClientSettings").GetFromJsonAsync<List<UvwHolidayPlanner>>($"{_URL}/api/lookup/HolidayPlanner"))
.OrderBy(t => t.Title)
.ToList();
StateHasChanged();
}
Below is my class code:
public class UvwHolidayPlanner
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool IsAllDay { get; set; }
public int Pk { get; set; }
public string RecurrenceRule { get; set; }
public List<DateTime> RecurrenceException { get; set; }
public int RecurrenceId { get; set; }
}
And below is my API controller code:
[HttpPost]
[Route("HolidayPlanner")]
public void Post([FromBody] UvwHolidayPlanner item)
{
string SQLSTE = "EXEC [dbo].[usp_AddHolidayPlanner] #PK, #Title, #Description, #StartDate, #EndDate, #IsAllDay, #RecurrenceRule, #RecurrenceException, #RecurrenceId";
using (var context = new TestAppContext())
{
List<SqlParameter> param = new List<SqlParameter>
{
new SqlParameter { ParameterName = "#PK", Value = item.Pk },
new SqlParameter { ParameterName = "#Title", Value = item.Title },
new SqlParameter { ParameterName = "#Description", Value = item.Description },
new SqlParameter { ParameterName = "#StartDate", Value = item.StartDate },
new SqlParameter { ParameterName = "#EndDate", Value = item.EndDate },
new SqlParameter { ParameterName = "#IsAllDay", Value = item.IsAllDay },
new SqlParameter { ParameterName = "#RecurrenceRule", Value = item.RecurrenceRule },
new SqlParameter { ParameterName = "#RecurrenceException", Value = item.RecurrenceException },
new SqlParameter { ParameterName = "#RecurrenceId", Value = item.RecurrenceId }
};
context.Database.ExecuteSqlRaw(SQLSTE, param);
}
}

How can get a list data of Google Sheets based on column names in Entity Framework

I'm modeling data search in Google Sheets using API (EF). I am currently connected to Google Sheets data. I also wrote a search based on RowId it's ok. Everything works fine. However I can't find data based on Id. Everything I have:
ItemGoogleSheet.cs
public class ItemGoogleSheet
{
public string Id { get; set; }
public string Name { get; set; }
}
ItemsGoogleSheetMapper.cs
public class ItemsGoogleSheetMapper
{
public static List<ItemGoogleSheet> MapFromRangeData(IList<IList<object>> values)
{
var items = new List<ItemGoogleSheet>();
foreach (var value in values)
{
ItemGoogleSheet item = new()
{
Id = value[0].ToString(),
Name = value[1].ToString(),
};
items.Add(item);
}
return items;
}
public static IList<IList<object>> MapToRangeData(ItemGoogleSheet item)
{
var objectList = new List<object>() { item.Id, item.Name };
var rangeData = new List<IList<object>> { objectList };
return rangeData;
}
}
ItemsGoogleSheetVATController.cs
public class ItemsGoogleSheetVATController : ControllerBase
{
const string SPREADSHEET_ID = "xxxx";
const string SHEET_NAME = "xx";
SpreadsheetsResource.ValuesResource _googleSheetValues;
public ItemsGoogleSheetVATController(GoogleSheetsHelper googleSheetsHelper)
{
_googleSheetValues = googleSheetsHelper.Service.Spreadsheets.Values;
}
[HttpGet("{rowId}")]
public IActionResult GetRowID(int rowId)
{
var range = $"{SHEET_NAME}!A{rowId}:AG{rowId}";
var request = _googleSheetValues.Get(SPREADSHEET_ID, range);
var response = request.Execute();
var values = response.Values;
return Ok(ItemsGoogleSheetMapper.MapFromRangeData(values).FirstOrDefault());
}
[HttpGet]
public IActionResult GetID(string id)
{
//How to get Data from Id
//return Ok();
}
}
My Google Sheets Data:
As in my description. I want to find Id = 0102 then it will output a list of results of: 0102, 01022101, 01022102
How can I get list of data based on Id column. Asking for any solutions from everyone. Thank you!
I have solved the problem. Thank you!

TryGetObjectByKey() doesn't return entity with Added state (EF 6)

1. Q #1
I have POCO
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public ICollection<Version> Versions { get; set; }
}
In my DbContext I have func
public void AttachUpdated<T>( T objectDetached) where T : class
{
var objContext = ((IObjectContextAdapter)this).ObjectContext;
var objSet = objContext.CreateObjectSet<T>();
var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, objectDetached);
object original;
if (objContext.TryGetObjectByKey(entityKey, out original))
objContext.ApplyCurrentValues(entityKey.EntitySetName, objectDetached);
else
objContext.AddObject(entityKey.EntitySetName, objectDetached);}
So i want to add some Products to context
var p1 = new Product(){Id = "1", Name = "Product 1";}
var p2 = new Product(){Id = "1", Name = "Product 1";}
ctx.AttachUpdated(p1);
And when i try to add identical Product (with same Id as first product) TryGetObjectByKey() doesn't find already added product.
ctx.AttachUpdated(p2);
Therefore I need to use ctx.SaveChanges() or AccseptAllChanges() and then
ctx.AttachUpdated(p2) work as expected.
I can't understand where i have problem in my code.
Q #2
var p1 = new Product() { Id = "1", Name = "Product 1" };
var v1 = new Version() { Number = "1.0", Type = "Release", ReleaseDate = "01/01/13" };
p1.Versions = new List<Version>();
p1.Versions.Add(v1);
ctx.AttachUpdated(p1);
And then i see that v1 was addet to DbSet(). But why? And how i could prevent such bihavior. I need to add only Product and not related Versions.
public void AttachOrUpdate<T>(T entity) where T : class
{
var objContext = ((IObjectContextAdapter)context).ObjectContext;
var objSet = objContext.CreateObjectSet<T>();
var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entity);
var original = this.context.Set<T>().Find(entityKey.EntityKeyValues[0].Value);
if (original != null)
{
this.context.Entry<T>(original).CurrentValues.SetValues(entity);
}
else
objContext.AddObject(entityKey.EntitySetName, entity);
}

Why do I get different values from my EntitySet depending on how I LINQ to it?

In debugging the issue in this thread: InvalidCastException when querying nested collection with LINQ I found out that something is wrong with how my Category EntitySet is populated. After selecteding a Category and throwing this exception to see what's going on I get this:
throw new Exception("CID: " + cat.CategoryID +
" LCID: " + cat.LocalizedCategories.First().LocalizedCategoryID +
" CID from LC: " + cat.LocalizedCategories.First().Category.CategoryID);
CID: 352 LCID: 352 CID from LC: 191
What am I doing wrong that causes CategoryID to have different values depending on how I LINQ to it? It should be 191, and not the same value as the LocalizedCategoryID.
This is the code I use to get the Category:
int categoryId = 352; // In reality this comes from a parameter and is supposed
// to be 191 to get the Category.
var cat = categoriesRepository.Categories.First(c => c.CategoryID == categoryId);
This is my domain object with some unrelated stuff stripped:
[Table(Name = "products")]
public class Product
{
[HiddenInput(DisplayValue = false)]
[Column(Name = "id", IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int ProductID { get; set; }
[Required(ErrorMessage = "Please enter a product name")]
[Column]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter a description")]
[DataType(DataType.MultilineText)]
[Column(Name = "info")]
public string Description { get; set; }
private EntitySet<Category> _Categories = new EntitySet<Category>();
[System.Data.Linq.Mapping.Association(Storage = "_Categories", OtherKey = "CategoryID")]
public ICollection<Category> Categories
{
get { return _Categories; }
set { _Categories.Assign(value); }
}
}
[Table(Name = "products_types")]
public class Category
{
[HiddenInput(DisplayValue = false)]
[Column(Name = "id", IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int CategoryID { get; set; }
public string NameByCountryId(int countryId)
{
return _LocalizedCategories.Single(lc => lc.CountryID == countryId).Name;
}
private EntitySet<LocalizedCategory> _LocalizedCategories = new EntitySet<LocalizedCategory>();
[System.Data.Linq.Mapping.Association(Storage = "_LocalizedCategories", OtherKey = "LocalizedCategoryID")]
public ICollection<LocalizedCategory> LocalizedCategories
{
get { return _LocalizedCategories; }
set { _LocalizedCategories.Assign(value); }
}
private EntitySet<Product> _Products = new EntitySet<Product>();
[System.Data.Linq.Mapping.Association(Storage = "_Products", OtherKey = "ProductID")]
public ICollection<Product> Products
{
get { return _Products; }
set { _Products.Assign(value); }
}
}
[Table(Name = "products_types_localized")]
public class LocalizedCategory
{
[HiddenInput(DisplayValue = false)]
[Column(Name = "id", IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public int LocalizedCategoryID { get; set; }
[Column(Name = "products_types_id")]
private int CategoryID;
private EntityRef<Category> _Category = new EntityRef<Category>();
[System.Data.Linq.Mapping.Association(Storage = "_Category", ThisKey = "CategoryID")]
public Category Category
{
get { return _Category.Entity; }
set { _Category.Entity = value; }
}
[Column(Name = "country_id")]
public int CountryID { get; set; }
[Column]
public string Name { get; set; }
}
This (in class Category) looks weird:
[System.Data.Linq.Mapping.Association(Storage = "_LocalizedCategories",
OtherKey = "LocalizedCategoryID" )] // ????
public ICollection<LocalizedCategory> LocalizedCategories
Category has a collection of LocalizedCategorys, which means that in the database the table products_types_localized has a foreign keyCategoryID. That field should be the "OtherKey". How was this mapping generated?

Optgroup drop-down support in MVC - Problems with Model Binding

I wonder if anyone can shed some light on this problem..
I've got an option group drop-down for selecting a person's ethnicity – however it’s not storing the value in the model.
ViewModel
[UIHint("EthnicOriginEditorTemplate")]
[DisplayName("Question 6: Ethnic Origin")]
public int EthnicOrigin { get; set; }
Helper : GroupDropList.Cs
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;
namespace Public.Helpers
{
public static class GroupDropListExtensions
{
public static string GroupDropList(this HtmlHelper helper, string name, IEnumerable<GroupDropListItem> data, int SelectedValue, object htmlAttributes)
{
if (data == null && helper.ViewData != null)
data = helper.ViewData.Eval(name) as IEnumerable<GroupDropListItem>;
if (data == null) return string.Empty;
var select = new TagBuilder("select");
if (htmlAttributes != null)
select.MergeAttributes(new RouteValueDictionary(htmlAttributes));
select.GenerateId(name);
var optgroupHtml = new StringBuilder();
var groups = data.ToList();
foreach (var group in data)
{
var groupTag = new TagBuilder("optgroup");
groupTag.Attributes.Add("label", helper.Encode(group.Name));
var optHtml = new StringBuilder();
foreach (var item in group.Items)
{
var option = new TagBuilder("option");
option.Attributes.Add("value", helper.Encode(item.Value));
if (SelectedValue != 0 && item.Value == SelectedValue)
option.Attributes.Add("selected", "selected");
option.InnerHtml = helper.Encode(item.Text);
optHtml.AppendLine(option.ToString(TagRenderMode.Normal));
}
groupTag.InnerHtml = optHtml.ToString();
optgroupHtml.AppendLine(groupTag.ToString(TagRenderMode.Normal));
}
select.InnerHtml = optgroupHtml.ToString();
return select.ToString(TagRenderMode.Normal);
}
}
public class GroupDropListItem
{
public string Name { get; set; }
public List<OptionItem> Items { get; set; }
}
public class OptionItem
{
public string Text { get; set; }
public int Value { get; set; }
}
}
This is my EditorTemplate
<%# Import Namespace="Public.Helpers"%>
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<int>"%>
<%=Html.GroupDropList("EthnicOrigin",
new[]
{
new GroupDropListItem
{
Name = "Ethnicity",
Items = new List<OptionItem>
{
new OptionItem {Value = 0, Text = "Please Select"}
}
},
new GroupDropListItem
{
Name = "a) White",
Items = new List<OptionItem>
{
new OptionItem {Value = 1, Text = "British"},
new OptionItem {Value = 2, Text = "Irish"},
new OptionItem {Value = 3, Text = "Other White (Please specify below)"}
}
},
--snip
}, Model, null)%>
And in the view I'm referencing it as:
<%=Html.EditorFor(x => x.EthnicOrigin, "EthnicOriginEditorTemplate")%>
However it's not passing through the selected Value into the model... has anyone experienced similar problems... many thanks in advance for some pointers.
Your select doesn't have a name attribute and so when you submit the form the selected value is not sent to the server. You need to add a name:
select.GenerateId(name);
select.MergeAttribute("name", name);
Just changed the helper class to get it work for MVC 3 and with nullable int.
Thanks a lot for the class, saves me plenty of time.
public static class GroupDropListExtensions
{
public static MvcHtmlString GroupDropList(this HtmlHelper helper, string name, IEnumerable<GroupDropListItem> data, int? SelectedValue, object htmlAttributes)
{
if (data == null && helper.ViewData != null)
data = helper.ViewData.Eval(name) as IEnumerable<GroupDropListItem>;
if (data == null) return new MvcHtmlString(string.Empty);
var select = new TagBuilder("select");
if (htmlAttributes != null)
select.MergeAttributes(new RouteValueDictionary(htmlAttributes));
select.GenerateId(name);
select.MergeAttribute("name", name);
var optgroupHtml = new StringBuilder();
var groups = data.ToList();
foreach (var group in data)
{
var groupTag = new TagBuilder("optgroup");
groupTag.Attributes.Add("label", helper.Encode(group.Name));
var optHtml = new StringBuilder();
foreach (var item in group.Items)
{
var option = new TagBuilder("option");
option.Attributes.Add("value", helper.Encode(item.Value));
if (SelectedValue != 0 && item.Value == SelectedValue)
option.Attributes.Add("selected", "selected");
option.InnerHtml = helper.Encode(item.Text);
optHtml.AppendLine(option.ToString(TagRenderMode.Normal));
}
groupTag.InnerHtml = optHtml.ToString();
optgroupHtml.AppendLine(groupTag.ToString(TagRenderMode.Normal));
}
select.InnerHtml = optgroupHtml.ToString();
return new MvcHtmlString(select.ToString(TagRenderMode.Normal));
}
}
public class GroupDropListItem
{
public string Name { get; set; }
public List<OptionItem> Items { get; set; }
}
public class OptionItem
{
public string Text { get; set; }
public int Value { get; set; }
}
This is supported natively using SelectListGroup as of ASP.NET MVC 5.2:
var items = new List<SelectListItem>();
var group1 = new SelectListGroup() { Name = "Group 1" };
items.Add(new SelectListItem() { Text = "Item1", Group = group1 });
Then in MVC, do
#Html.DropDownList("select", items)