Manually Create classes to map to XML Request - c#

This question is very similar to this one. That question asks if it's worth the trouble to create classes to deal with an api xml response. My question is the opposite: is it worth it to create classes to build an api request vs simply hard-coding the xml?
This is an example of the latter:
string browseService = "http://Mydomain/SearchSvc/CVWebService.svc/DoBrowse";
var browseRequest = string.Format("<databrowse_BrowseRequest opType=\"{0}\">" +
"<entity clientName=\"{1}\" applicationId=\"{2}\" clientId=\"{3}\" subclientId=\"{4}\" backupsetId=\"{5}\" instanceId=\"{6}\"/>" +
"<paths path=\"{7}\"/><options showDeletedFiles=\"1\" restoreIndex=\"1\"/><mode mode=\"2\"/><queries type=\"1\" queryId=\"countQuery\">" +
"<aggrParam aggrType=\"4\" field=\"0\"/></queries><queries type=\"0\" queryId=\"dataQuery\">" +
"<dataParam><paging firstNode=\"0\" skipNode=\"0\" pageSize=\"15\"/><sortParam ascending=\"1\">" +
"<sortBy val=\"38\"/><sortBy val=\"0\"/></sortParam></dataParam></queries></databrowse_BrowseRequest>",
"2", "testServer123", "29", "1234", "5678", "9123", "1", "/tmp/somefile.txt");
if (browseClientResp.StatusCode == HttpStatusCode.OK)
{
XmlDocument xmlDoc = new XmlDocument();
var test = browseClientResp.GetResponseStream();
xmlDoc.Load(test);
}
And here is an example of the classes I created for the former case:
[XmlRoot("databrowse_BrowseRequest")]
public class CommVaultBrowse
{
[XmlAttribute("opType")]
public int OpType { get; set; }
[XmlElement("session")]
public Session Session { get; set; }
[XmlElement("entity")]
public Entity Entity { get; set; }
[XmlElement("paths")]
public List<Paths> Paths { get; set; }
[XmlElement("timeRange")]
public TimeRange TimeRange { get; set; }
[XmlElement("options")]
public Options Options { get; set; }
[XmlElement("mode")]
public Mode Mode { get; set; }
[XmlElement("queries")]
public List<Queries> Queries { get; set; }
}
public class Session
{
[XmlAttribute("sessionId")]
public int SessionId { get; set; }
}
public class Entity
{
[XmlAttribute("clientName")]
public string ClientName { get; set; }
[XmlAttribute("applicationId")]
public int ApplicationId { get; set; }
[XmlAttribute("clientId")]
public int ClientId { get; set; }
[XmlAttribute("subclientId")]
public string SubclientId { get; set; }
[XmlAttribute("backupSetId")]
public int BackupSetId { get; set; }
[XmlAttribute("instanceId")]
public int InstanceId { get; set; }
}
public class Paths
{
[XmlAttribute("path")]
public string Path { get; set; }
}
public class TimeRange
{
[XmlAttribute("toTime")]
public int ToTime { get; set; }
[XmlAttribute("fromTime")]
public int FromTime { get; set; }
}
public class Options
{
[XmlAttribute("showDeletedFiles")]
public byte ShowDeletedFiles { get; set; }
[XmlAttribute("restoreIndex")]
public byte RestroeIndex { get; set; }
}
public class Mode
{
//the only valid value according to Commvault documentation is 2
[XmlAttribute("mode")]
public int ModeId { get; set; }
}
public class Queries
{
[XmlAttribute("type")]
public int Type { get; set; }
[XmlAttribute("queryId")]
public int QueryId { get; set; }
[XmlElement("aggrParam")]
public AggregateParams AggrParam { get; set; }
[XmlElement("dataParam")]
public DataParams DataParam { get; set; }
}
public class AggregateParams
{
[XmlAttribute("aggrType")]
public int AggrType { get; set; }
[XmlAttribute("field")]
public int Field { get; set; }
}
public class DataParams
{
[XmlElement("paging")]
public Paging Paging { get; set; }
[XmlElement("sortParam")]
public SortParam SortParam { get; set; }
}
public class Paging
{
[XmlAttribute("firstNode")]
public int FirstNode { get; set; }
[XmlAttribute("skipNode")]
public int SkipNode { get; set; }
[XmlAttribute("pageSize")]
public int PageSize { get; set; }
}
public class SortParam
{
[XmlAttribute("ascending")]
public int Ascending { get; set; }
[XmlElement("sortBy")]
public List<SortBy> SortBys { get; set; }
}
public class SortBy
{
[XmlAttribute("val")]
public int Val { get; set; }
}
I realized after the fact that instantiating an object of type CommVaultBrowse could get kinda complicated:
var test = new CommVaultBrowse
{
OpType = 2,
Session = new Session
{
SessionId = 1234
},
Entity = new Entity
{
ApplicationId = 29,
BackupSetId = 222,
ClientId = 333,
ClientName = "testServer123",
InstanceId = 1,
SubclientId = "subclient1"
},
Paths = new List<Paths>
{
new Paths
{
Path = "\\C:\\Users\\Administrator\\Desktop\\"
}
},
TimeRange = new TimeRange
{
FromTime = 1378180800,
ToTime = 1378439999
},
Options = new Options
{
RestroeIndex = 1,
ShowDeletedFiles = 0
},
Mode = new Mode
{
ModeId = 2
},
Queries = new List<Queries>
{
new Queries
{
Type = 0, QueryId = 1,
AggrParam = new AggregateParams
{
AggrType = 0,
Field = 1
}
},
new Queries
{
Type = 0,
QueryId = 1,
DataParam = new DataParams
{
Paging = new Paging
{
FirstNode = 1,
PageSize = 20,
SkipNode = 0
},
SortParam = new SortParam
{
Ascending = 1,
SortBys = new List<SortBy>
{
new SortBy
{
Val = 1
},
new SortBy
{
Val = 2
}
}
}
}
}
}
};
Is there a standard way of building these types of requests?

Build an XSD file that would allow you to validate your xml.
Then used XSD.exe to create the classes that would serialize into your xml.
https://msdn.microsoft.com/en-us/library/x6c1kb0s(v=vs.110).aspx
Serialize an object to string

Related

How to insert into an enumerable list, which is an member of another list

I have an AcadamicFee list, at one point in time I want to insert an item under Fee. So that, it should add like Fee[1], Fee[2].modified the code like below.
I want to insert one new item under Fee list. But it didn't reflect. How to update the AcadamicFee list through Linq?
Thanks in advance.
AcadamicFee[0]
{
----
----
----
TermDetails [0]
{
---
Fee[0]
Fee[1]
Fee[2]
}
}
public class Fee
{
public int FeeID { get; set; }
public string FeeName { get; set; }
public string FeeAmount { get; set; }
public string IsFineApplicable { get; set; }
public string LastDate { get; set; }
}
public class Ter
{
public int TermID { get; set; }
public string TermName { get; set; }
public IEnumerable<Fee> FeeDetails { get; set; }
}
public class AcadamicFee
{
public int id { get; set; }
public string AdmissionID { get; set; }
public string StudentName { get; set; }
public int Class { get; set; }
public string AcadamicYear { get; set; }
public Nullable<int> TotalPaid { get; set; }
public Nullable<int> AcadamicAmount { get; set; }
public Nullable<int> BalanceAmount { get; set; }
public IEnumerable<Term> TermDetails { get; set; }
}
Any clue how to do with Linq? I tried something like this:
for (var i = 0; i < fees.Count; i++)
{
bool termDetailsExist = acadamic_fee.Any(a => a.TermDetails.Any(b => b.TermID == fees[i].TermID));
if (termDetailsExist)
{
foreach (AcadamicFeeModel acm in acadamic_fee)
{
foreach (TermModel trm in acm.TermDetails)
{
if (trm.TermID == fees[i].TermID)
{
List<FeeModel> FeeType = new List<FeeModel>();
FeeType.Add(new FeeModel
{
FeeID = fees[i].FeeID,
FeeName = fees[i].FeeName,
FeeAmount = fees[i].FeeAmount,
IsFineApplicable = fees[i].IsFineApplicable,
LastDate = fees[i].LastDate,
});
trm.FeeDetails.ToList().AddRange(FeeType);
}
}
}
}
}
trm.FeeDetails.ToList().AddRange(FeeType);
You've created a new List<FeeModel>, added a copy of the FeeDetails sequence, added a new FeeModel object, and then thrown the new list away.
You need to store the modified list in the property - for example:
foreach (TermModel trm in acm.TermDetails)
{
if (trm.TermID == fees[i].TermID)
{
List<FeeModel> FeeType = new List<FeeModel>();
FeeType.Add(new FeeModel
{
FeeID = fees[i].FeeID,
FeeName = fees[i].FeeName,
FeeAmount = fees[i].FeeAmount,
IsFineApplicable = fees[i].IsFineApplicable,
LastDate = fees[i].LastDate,
});
FeeType.AddRange(trm.FeeDetails);
trm.FeeDetails = FeeType;
}
}

How do I LINQ nested lists to JSON in Web Api 2?

I am creating a web api that returns Json. My out put looks like this:
[
{
"NodeID":1252,
"CASNumber":"1333-86-4",
"EINECSCode":"215-609-9",
"EUIndex":"215-609-9",
"Duty":"No",
"Prohibited":"No",
"Unwanted":"No",
"IsReach":"No",
"SubstanceName":"Carbon black",
"GroupName":"Renault Complete",
"Portion":0.100000
},
{
"NodeID":1252,
"CASNumber":"1333-86-4",
"EINECSCode":"215-609-9",
"EUIndex":"215-609-9",
"Duty":"No",
"Prohibited":"No",
"Unwanted":"No",
"IsReach":"No",
"SubstanceName":"Carbon black",
"GroupName":"Renault Orange",
"Portion":0.100000
}
]
I Am trying to create nested Json with an ouptut like this:
{
"NodeID":1252,
"CASNumber":"1333-86-4",
"EINECSCode":"215-609-9",
"EUIndex":"215-609-9",
"Duty":"No",
"Prohibited":"No",
"Unwanted":"No",
"IsReach":"No",
"SubstanceName":"Carbon black",
"GroupName":[
{
"name":"Renault Complete"
},
{
"name":"Renault Orange"
}
],
"Portion":0.100000
}
This is my class:
public class BasicSubstances
{
public int NodeID { get; set; }
public string CASNumber { get; set; }
public string EINECSCode { get; set; }
public string EUIndex { get; set; }
public string Duty { get; set; }
public string Prohibited { get; set; }
public string Unwanted { get; set; }
public string IsReach { get; set; }
public string SubstanceName { get; set; }
public string GroupName { get; set; }
public decimal ?Portion { get; set; }
}
And this is my controller:
public List<BasicSubstances> GetBasicSubstance(string partNumber, string version, int nodeID, int parentID )
{
IMDSDataContext dc = new IMDSDataContext();
List<BasicSubstances> results = new List<BasicSubstances>();
foreach (spGetBasicSubstanceResult part in dc.spGetBasicSubstance( partNumber, version, nodeID, parentID))
{
results.Add(new BasicSubstances()
{
NodeID = part.NodeID,
CASNumber = part.CASNumber,
EINECSCode = part.EINECSCode,
EUIndex = part.EINECSCode,
Duty = part.Duty,
Prohibited = part.Prohibited,
Unwanted = part.Unwanted,
IsReach = part.ISReach,
SubstanceName = part.SynonymName,
GroupName = part.GroupName,
Portion = part.Portion
});
}
return results;
}
My Json looks like the first output, I need it to look like the second output.
I totally lost, any help would be appreciated.
Well, you can try the following:
Your models:
public class BasicSubstanceViewModel
{
public int NodeID { get; set; }
public string CASNumber { get; set; }
public string EINECSCode { get; set; }
public string EUIndex { get; set; }
public string Duty { get; set; }
public string Prohibited { get; set; }
public string Unwanted { get; set; }
public string IsReach { get; set; }
public string SubstanceName { get; set; }
public List<GroupName> GroupName { get; set; }
public decimal ?Portion { get; set; }
}
public class GroupName
{
public string Name { get; set; }
}
Your method:
public BasicSubstanceViewModel GetBasicSubstance(string partNumber, string version, int nodeID, int parentID )
{
IMDSDataContext dc = new IMDSDataContext();
var spResult = dc.spGetBasicSubstance( partNumber, version, nodeID, parentID).ToList();
if(!spResult.Any())
{
return null;
}
var firstPart = spResult[0];
var result = new BasicSubstanceViewModel
{
NodeID = firstPart.NodeID,
CASNumber = firstPart.CASNumber,
EINECSCode = firstPart.EINECSCode,
EUIndex = firstPart.EINECSCode,
Duty = firstPart.Duty,
Prohibited = firstPart.Prohibited,
Unwanted = firstPart.Unwanted,
IsReach = firstPart.ISReach,
SubstanceName = firstPart.SynonymName,
GroupName = spResult.Select(p => new GroupName { Name = p.GroupName }).ToList(),
Portion = firstPart.Portion
};
return result;
}
Hope it will help.

c# POST json not working as expected?

I have this example python script that im trying to convert to c# using newtonsoft :
import urllib
import urllib2
import json
url = 'http://server.net/fcgi/scrut_fcgi.fcgi'
report_details = {
'reportTypeLang' : 'conversations',
'reportDirections' : {
'selected' : 'inbound'
},
'times' : {
'dateRange' : 'Last5Minutes'
},
'filters' : {
'sdfDips_0' : 'in_AC10033A_AC10033A-410'
},
'dataGranularity' : {
'selected' : 'auto'
}
}
data_i_need = {
'inbound' : {
'table' : {
'query_limit' : {
'offset' : 0,
'max_num_rows' : 1
}
}
},
'outbound' : {
'table' : {
'query_limit' : {
'offset' : 0,
'max_num_rows' : 1
}
}
}
}
data = {
'rm' : 'report_api',
'action' : 'get',
'rpt_json' : json.dumps( report_details ),
'data_requested' : json.dumps( data_i_need )
}
data = urllib.urlencode( data )
req = urllib2.Request( url, data )
response = urllib2.urlopen( req )
report = response.read()
report_obj = json.loads( report )
so far with some help i have the following c# code but it does not return any data like the python version just errors as if the request is incorrect:
class Program
{
static void Main(string[] args)
{
ReportDirections reportDirections = new ReportDirections();
reportDirections.selected = "inbound";
Times Times = new Times();
Times.dateRange = "Last5Minutes";
Filters Filters = new Filters();
Filters.sdfDips_0 = "in_AC10033A_AC10033A-410";
DataGranularity DataGranularity = new DataGranularity();
DataGranularity.selected = "auto";
ReportDetails ReportDetails = new ReportDetails();
ReportDetails.reportTypeLang = "conversations";
ReportDetails.reportDirections = reportDirections;
ReportDetails.times = Times;
ReportDetails.filters = Filters;
ReportDetails.dataGranularity = DataGranularity;
//
QueryLimit QueryLimit = new QueryLimit();
QueryLimit.offset = 0;
QueryLimit.max_num_rows = 1;
QueryLimit2 QueryLimit2 = new QueryLimit2();
QueryLimit2.offset = 0;
QueryLimit2.max_num_rows = 1;
Table Table = new Table();
Table.query_limit = QueryLimit;
Table2 Table2 = new Table2();
Table2.query_limit = QueryLimit2;
Inbound Inbound = new Inbound();
Inbound.table = Table;
Outbound Outbound = new Outbound();
Outbound.table = Table2;
DataINeed DataINeed = new DataINeed();
DataINeed.inbound = Inbound;
DataINeed.outbound = Outbound;
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://server.bobo.net/fcgi/scrut_fcgi.fcgi");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
var serializer = new Newtonsoft.Json.JsonSerializer();
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
using (var tw = new Newtonsoft.Json.JsonTextWriter(streamWriter))
{
serializer.Serialize(tw,
new
{
action = "get",
rm = "report_api",
data_requested = DataINeed,
rpt_json = ReportDetails
});
}
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
Console.WriteLine(responseText);
}
}
}
public class tw
{
public string rm { get; set; }
public string action { get; set; }
public string rpt_json { get; set; }
public string data_requested { get; set; }
}
public class DataINeed
{
public Inbound inbound { get; set; }
public Outbound outbound { get; set; }
}
public class Inbound
{
public Table table { get; set; }
}
public class Outbound
{
public Table2 table { get; set; }
}
public class Table
{
public QueryLimit query_limit { get; set; }
}
public class Table2
{
public QueryLimit2 query_limit { get; set; }
}
public class QueryLimit
{
public int offset { get; set; }
public int max_num_rows { get; set; }
}
public class QueryLimit2
{
public int offset { get; set; }
public int max_num_rows { get; set; }
}
public class ReportDetails
{
public string reportTypeLang { get; set; }
public ReportDirections reportDirections { get; set; }
public Times times { get; set; }
public Filters filters { get; set; }
public DataGranularity dataGranularity { get; set; }
}
public class ReportDirections
{
public string selected { get; set; }
}
public class Times
{
public string dateRange { get; set; }
}
public class Filters
{
public string sdfDips_0 { get; set; }
}
public class DataGranularity
{
public string selected { get; set; }
}
public class bob
{
}
does this look like the correct way to POST the json request or does something look wrong?
Thanks
Try this..
using System.Net;
using Newtonsoft.Json;
class Program
{
static void Main(string[] args)
{
ReportDirections reportDirections = new ReportDirections();
reportDirections.selected = "inbound";
Times Times = new Times();
Times.dateRange = "Last5Minutes";
Filters Filters = new Filters();
Filters.sdfDips_0 = "in_AC10033A_AC10033A-410";
DataGranularity DataGranularity = new DataGranularity();
DataGranularity.selected = "auto";
ReportDetails ReportDetails = new ReportDetails();
ReportDetails.reportTypeLang = "conversations";
ReportDetails.reportDirections = reportDirections;
ReportDetails.times = Times;
ReportDetails.filters = Filters;
ReportDetails.dataGranularity = DataGranularity;
//
QueryLimit QueryLimit = new QueryLimit();
QueryLimit.offset = 0;
QueryLimit.max_num_rows = 1;
QueryLimit2 QueryLimit2 = new QueryLimit2();
QueryLimit2.offset = 0;
QueryLimit2.max_num_rows = 1;
Table Table = new Table();
Table.query_limit = QueryLimit;
Table2 Table2 = new Table2();
Table2.query_limit = QueryLimit2;
Inbound Inbound = new Inbound();
Inbound.table = Table;
Outbound Outbound = new Outbound();
Outbound.table = Table2;
DataINeed DataINeed = new DataINeed();
DataINeed.inbound = Inbound;
DataINeed.outbound = Outbound;
WebClient _webClient = new WebClient();
_webClient.Headers.Add("Content-Type", "application/json");
string data_requested = HttpUtility.UrlEncode(JsonConvert.SerializeObject(DataINeed));
string rpt_json = HttpUtility.UrlEncode(JsonConvert.SerializeObject(ReportDetails));
string data = "action=get&rm=report_api&data_requested=" + data_requested + "&rpt_json="+rpt_json;
string address = "http://server/fcgi/scrut_fcgi.fcgi";
var responseText = Encoding.Default.GetString(_webClient.UploadData(address, "POST", Encoding.Default.GetBytes(data)));
Console.WriteLine(responseText);
}
}
public class tw
{
public string rm { get; set; }
public string action { get; set; }
public string rpt_json { get; set; }
public string data_requested { get; set; }
}
public class DataINeed
{
public Inbound inbound { get; set; }
public Outbound outbound { get; set; }
}
public class Inbound
{
public Table table { get; set; }
}
public class Outbound
{
public Table2 table { get; set; }
}
public class Table
{
public QueryLimit query_limit { get; set; }
}
public class Table2
{
public QueryLimit2 query_limit { get; set; }
}
public class QueryLimit
{
public int offset { get; set; }
public int max_num_rows { get; set; }
}
public class QueryLimit2
{
public int offset { get; set; }
public int max_num_rows { get; set; }
}
public class ReportDetails
{
public string reportTypeLang { get; set; }
public ReportDirections reportDirections { get; set; }
public Times times { get; set; }
public Filters filters { get; set; }
public DataGranularity dataGranularity { get; set; }
}
public class ReportDirections
{
public string selected { get; set; }
}
public class Times
{
public string dateRange { get; set; }
}
public class Filters
{
public string sdfDips_0 { get; set; }
}
public class DataGranularity
{
public string selected { get; set; }
}
public class bob
{
}
managed to get it working by changing the content-type to :
_webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
i was debugging with charles and the python version was posting a json formated form, changed the c# content type to match and now works a treat
Many Thanks for your code and help.

Custom Mapping Dapper.NET

I could done like this but I think there should be a way to do this better;
Resource.ResourceIncrease resource = new Resource.ResourceIncrease();
using (IDbConnection connection = OpenConnection())
{
dynamic reader = connection.Query<dynamic>("UserResourceGet", new { UserId = UserId }, commandType: CommandType.StoredProcedure).SingleOrDefault();
resource.Wood.value = reader.Wood;
resource.Wood.increase = reader.WoodIncome;
resource.Food.value = reader.Food;
resource.Food.increase = reader.FoodIncome;
resource.Stone.value = reader.Stone;
resource.Stone.increase = reader.StoneIncome;
resource.Gold.value = reader.Gold;
resource.Gold.increase = reader.GoldIncome;
}
return resource;
SQL SP >
SELECT Wood, Food, Stone, Gold, WoodIncome, FoodIncome, StoneIncome, GoldIncome
FROM Resources WHERE UserId = #UserId
Class >
public class Resource
{
public int Wood { get; set; }
public int Food { get; set; }
public int Stone { get; set; }
public int Gold { get; set; }
}
public class ResourceIncrease
{
public Increase Wood{ get; set; }
public Increase Food { get; set; }
public Increase Stone { get; set; }
public Increase Gold { get; set; }
public ResourceIncrease()
{
this.Wood = new Increase();
this.Food = new Increase();
this.Stone = new Increase();
this.Gold = new Increase();
}
}
public class Increase
{
public int value { get; set; }
public int increase { get; set; }
}
I would create a class that match the return of the SP, and then would use AutoMapper (http://automapper.org/) to map that class to the ResourceIncrease class.
Check this
http://geekswithblogs.net/EltonStoneman/archive/2012/01/03/mapping-and-auto-mapping-objects.aspx

EF5 The changes to the database were committed successfully ... Unable to set field/property

I have been searching for days now trying to figure this one out. It saves my records correctly but throws the following error:
The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: Unable to set field/property Actors on entity type BOR.DataModel.StagComplaint. See InnerException for details.
I am using Code First and EF 5 in a C# Web Forms solution with a supporting WCF Service. Here are my POCO classes:
public partial class StagComplaint : ComplaintBase {
public IList<StagParcel> Parcels { get; set; }
public IList<StagActor> Actors { get; set; }
public IList<StagRectification> Rectifications { get; set; }
public ComplaintType ComplaintType { get; set; }
public int ComplaintTypeID { get; set; }
public StagComplaint() {
this.Parcels = new List<StagParcel>();
this.Actors = new List<StagActor>();
this.Rectifications = new List<StagRectification>();
}
}
public class ComplaintBase : BORBase {
public string Number { get; set; }
public int ParentID { get; set; }
public int TaxYear { get; set; }
public string Category { get; set; }
public double BuildingValue { get; set; }
public double LandValue { get; set; }
public double OwnerOpinion { get; set; }
public string Notes { get; set; }
}
public class BORBase {
[Required]
public DateTime CreationDate { get; set; }
public int ID { get; set; }
[MaxLength(25)]
[Required]
public string UserIdentification { get; set; }
}
public partial class StagParcel : ParcelBase {
public virtual StagActor Owner { get; set; }
[ForeignKey("Owner")]
public int OwnerID { get; set; }
public StagAddress Address { get; set; }
[IgnoreDataMember]
public virtual StagComplaint Complaint { get; set; }
public int ComplaintID { get; set; }
public StagParcel() {
this.Address = new StagAddress();
}
}
public class ParcelBase : BORBase {
public string Number { get; set; }
public double BuildingValue { get; set; }
public double LandValue { get; set; }
public double OwnerOpinion { get; set; }
public string LandUseCode { get; set; }
public string NeighborhoodCode { get; set; }
public string TaxDistrict { get; set; }
public string SchoolDistrict { get; set; }
public int SchoolBoardID { get; set; }
}
public partial class StagActor : ActorBase {
public StagAddress Address { get; set; }
public virtual IList<StagEmail> Emails { get; set; }
public virtual IList<StagPhone> Phones { get; set; }
[IgnoreDataMember]
public virtual StagComplaint Complaint { get; set; }
public int ComplaintID { get; set; }
public virtual Role Role { get; set; }
public int RoleID { get; set; }
public StagActor() {
this.Emails = new List<StagEmail>();
this.Phones = new List<StagPhone>();
this.Address = new StagAddress();
}
}
public class ActorBase : BORBase {
public string Name { get; set; }
}
public class StagRectification : BORBase {
public bool Active { get; set; }
public string Notes { get; set; }
public virtual RectificationType RectificationType { get; set; }
public int RectificationTypeID { get; set; }
[IgnoreDataMember]
public virtual StagComplaint Complaint { get; set; }
public int ComplaintID { get; set; }
}
This is the client side code I am using to create the Complaint:
public int AddParcelsToStagingComplaint(List<string> parcelIDs, string userID) {
StagComplaint comp = new StagComplaint();
int Result = 0;
using (BORServiceClient db = new BORServiceClient()) {
comp = new StagComplaint() {
BuildingValue = 111222,
Category = "*",
LandValue = 222333,
Number = "*",
TaxYear = DateTime.Now.Year,
ComplaintTypeID = 1,
UserIdentification = userID,
CreationDate = DateTime.Now,
};
StagAddress ca = new StagAddress() { Line1 = "670 Harvard Blvd", City = "Cleveland", State = "OH", ZipCode = "44113", };
List<StagPhone> ps = new List<StagPhone>();
ps.Add(new StagPhone() { Number = "5556664646", Type = PhoneTypes.Home, UserIdentification = userID, CreationDate = DateTime.Now, });
comp.Actors.Add(
new StagActor() {
Name = "Joe Schmoe",
Address = ca,
Phones = ps,
RoleID = 1,
UserIdentification = userID,
CreationDate = DateTime.Now,
}
);
StagAddress aa = new StagAddress() {
City = wp.Address.City,
Line1 = wp.Address.Line1,
Line2 = wp.Address.Line2,
State = wp.Address.State,
ZipCode = wp.Address.ZipCode,
};
ps = new List<StagPhone>();
ps.Add(new StagPhone() { Number = "4448887878", Type = PhoneTypes.Work, UserIdentification = userID, CreationDate = DateTime.Now, });
StagParcel p = new StagParcel() {
Address = new StagAddress() { Line1 = "4 Oxford Drive", City = "Hudson", State = "OH", ZipCode = "44236" },
BuildingValue = wp.BuildingValue,
LandUseCode = wp.LandUseCode,
LandValue = wp.LandValue,
NeighborhoodCode = wp.NeighborhoodCode,
Number = wp.Number,
Owner = new StagActor() { Name = "Owner Person", Address = aa, RoleID = 2, Phones = ps, UserIdentification = userID, CreationDate = DateTime.Now, },
OwnerOpinion = wp.OwnerOpinion,
SchoolBoardID = wp.SchoolBoardID,
SchoolDistrict = wp.SchoolDistrict,
TaxDistrict = wp.TaxDistrict,
UserIdentification = userID,
CreationDate = DateTime.Now,
};
comp.Parcels.Add(p);
ServiceResponse<int> saved = db.AddComplaint((ComplaintBase)comp, Contexts.Staging, userID);
if (saved.WasSuccessful)
Result = saved.Result;
} // using the database
return Result;
} // AddParcelsToStagingComplaint - Method
Here is the WCF method that gets called:
using (StagComplaintRepo cr = new StagComplaintRepo()) {
cr.Add((StagComplaint)complaint, userID);
if (cr.Save()) {
Result.Result = complaint.ID;
Result.WasSuccessful = true;
} else {
Result.AddException(string.Format("Unable to create a new Complaint in the {0} context.", context));
} // if the save was successful
} // using the Complaint Repository
And here is the BaseRepository that has the Save and Add methods:
public abstract class BaseRepository<T> : IDisposable, IRepository<T> where T : class {
public virtual bool Save(bool detectChanges = false) {
if (detectChanges == true)
this.Entities.ChangeTracker.DetectChanges();
return (this.Entities.SaveChanges() > 0);
}
public virtual void Add(T entity, string userID) {
this.Entities.Set<T>().Add(entity);
}
...
}
It fails on the above this.Entities.SaveChanges() call with the error mentioned at the top of this post. There is no extra inner exception. If I only fill in the Complaint properties that are required and are part of that object, it works. But once I add a Parcel with an Actor it fails.
I assume it is something simple, perhaps a switch needs to be turned on or off. But similar errors all seem to reference AcceptChanges and that is not the issue here. At least based on the error message. Any help would be appreciated.
EDIT
Here is the full stack trace:
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
at BOR.WebService.Repositories.BaseRepository`1.Save(Boolean detectChanges) in d:\DevProjects\BOR\WebService\Main\Source\WebServiceSolution\WcfServiceProject\Repositories\BaseRepository.cs:line 22
at BOR.WebService.BORService.AddComplaint(ComplaintBase complaint, Contexts context, String userID) in d:\DevProjects\BOR\WebService\Main\Source\WebServiceSolution\WcfServiceProject\BORService.svc.cs:line 65
Line 22 is:
return (this.Entities.SaveChanges() > 0);
Line 65 is:
if (cr.Save()) {

Categories

Resources