The given key was not present in the dictionary Microsoft CRM Plugin - c#

Another Microsoft CRM plugin related question. My plugin is firing when an invoice record is updated. I want to copy the contents of some of the invoice fields to the corresponding fields on the commission record. The if which contains the due date seems to work ok but the if containing the invoiceamount gives a key not present error. I have checked that all the field names are correct and exist in the correct entities.
Any ideas what's happening? Do I need to use images and if so, could somebody help me with some code, please?
Thanks
// <copyright file="PreInvoiceUpdate.cs" company="">
// Copyright (c) 2013 All Rights Reserved
// </copyright>
// <author></author>
// <date>8/8/2013 10:40:22 AM</date>
// <summary>Implements the PreInvoiceUpdate Plugin.</summary>
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.1
// </auto-generated>
namespace UpdateCommission
{
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
/// <summary>
/// PreInvoiceUpdate Plugin.
/// Fires when the following attributes are updated:
/// All Attributes
/// </summary>
public class PreInvoiceUpdate : Plugin
{
/// <summary>
/// Initializes a new instance of the <see cref="PreInvoiceUpdate"/> class.
/// </summary>
public PreInvoiceUpdate()
: base(typeof(PreInvoiceUpdate))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(20, "Update", "invoice", new Action<LocalPluginContext>(ExecutePreInvoiceUpdate)));
// Note : you can register for more events here if this plugin is not specific to an individual entity and message combination.
// You may also need to update your RegisterFile.crmregister plug-in registration file to reflect any change.
}
/// <summary>
/// Executes the plug-in.
/// </summary>
/// <param name="localContext">The <see cref="LocalPluginContext"/> which contains the
/// <see cref="IPluginExecutionContext"/>,
/// <see cref="IOrganizationService"/>
/// and <see cref="ITracingService"/>
/// </param>
/// <remarks>
/// For improved performance, Microsoft Dynamics CRM caches plug-in instances.
/// The plug-in's Execute method should be written to be stateless as the constructor
/// is not called for every invocation of the plug-in. Also, multiple system threads
/// could execute the plug-in at the same time. All per invocation state information
/// is stored in the context. This means that you should not use global variables in plug-ins.
/// </remarks>
protected void ExecutePreInvoiceUpdate(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
// TODO: Implement your custom Plug-in business logic.
// Obtain the execution context from the service provider.
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
IServiceProvider serviceProvider = localContext.ServiceProvider;
ITracingService tracingService = localContext.TracingService;
// Obtain the target entity from the input parmameters.
//Entity contextEntity = (Entity)context.InputParameters["Target"];
if (context.Depth == 1)
{
#region Set up variables
Entity targetInvoice = null;
targetInvoice = (Entity)context.InputParameters["Target"];
Guid invoiceID = targetInvoice.Id;
ColumnSet invoiceCols = new ColumnSet("new_totalcomm", "new_grossprofit", "new_invoiceamount", "duedate");
//Entity contact = service.Retrieve("contact", cid, cols);
//contact.Attributes["jobtitle"] = "Sometitle";
// contact.Attributes["address1_line1"] = "Some address";
//service.Update(contact);
string fetchCommissionQuery = #"
<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
<entity name='tbw_commission'>
<attribute name='tbw_commissionid' />
<attribute name='tbw_name' />
<attribute name='createdon' />
<order attribute='tbw_name' descending='false' />
<filter type='and'>
<condition attribute='new_relatedinvoice' operator='eq' uitype='invoice' value='";
fetchCommissionQuery += invoiceID;
fetchCommissionQuery += #"' />
</filter>
</entity>
</fetch> ";
EntityCollection commissionCollection = service.RetrieveMultiple(new FetchExpression(fetchCommissionQuery));
//targetInvoice = service.Retrieve("invoice", invoiceID, invoiceCols);
#endregion
foreach (var commission in commissionCollection.Entities)
{
if (targetInvoice.Attributes["duedate"] != null)
{
commission.Attributes["tbw_duedate"] = targetInvoice.Attributes["duedate"];
}
if (targetInvoice.Attributes["new_invoiceamount"] != null)// && commission.Attributes["tbw_paymentrate"] != null)
{
//dynamic commRate = commission.Attributes["tbw_paymentrate"];
//dynamic invoiceTotal = ((Money)targetInvoice.Attributes["new_invoiceamount"]).Value;
//dynamic commTotal = commRate * invoiceTotal;
//commission.Attributes["tbw_total"] = new Money(commTotal);
//commission.Attributes["tbw_total"] = 1.02;
}
//commission.Attributes["tbw_name"] = "TestCommName";
service.Update(commission);
}
// dynamic currentInvoiceTotal = ((Money)targetInvoice.Attributes["new_invoiceamount"]).Value;
// currentInvoiceTotal = currentInvoiceTotal - 10;
// Entity invoice = service.Retrieve("invoice", invoiceID, invoiceCols);
// invoice.Attributes["new_grossprofit"] = new Money(currentInvoiceTotal);
//service.Update(invoice);
//}
}
}
}
}

In Update, you will only have the value of fields those are updated. Other fields won't be there in Target Entity. You need to register plugin with PreImage. Add the fields to PreImage you want to access in plugin.
preImage = (Entity)context.PreEntityImages["PreImage"];
How to Register Plugin with Image

Related

How to create a new tag in a local repo using LibGit2Sharp?

I want to create a new lightweight tag in my local repo using LibGit2Sharp. I have no intent to push it to the remote (I'm using tags as short-term bookmarks); knowing how to also push to the remote would be handy, but I am most interested in just creating a tag in a local repo without pushing to the remote.
As follows:
using LibGit2Sharp;
/// <summary>
/// Create a lightweight tag in the specified local repo:
/// </summary>
/// <param name="tagName">Name to be given to the tag</param>
/// <param name="repoFolder">Repo folder location (path)</param>
/// <param name="commitSha">Hash identifying the commit to receive the tag</param>
public static void CreateTag(string tagName, string repoFolder, string commitSha)
{
using (var repo = new Repository(repoFolder))
{
var commit = repo.Lookup<Commit>(commitSha);
if (commit != null)
{
repo.ApplyTag(tagName, commitSha);
}
}
}

Add Root element to XML log4net

I have tried to create XML log file using log4net and it create log successfully but without root element
my question how to create the root element
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="logger.xml" type="log4net.Util.PatternString" />
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="20"/>
<maximumFileSize value="10000KB"/>
<staticLogFileName value="true"/>
<preserveLogFileNameExtension value="true" />
<layout type="Log4net1.CustomXmlLayoutSchemaLog4j">
<locationInfo value="true" />
</layout>
</appender>
<event logger="SomeName2" time="4/16/2019 2:45:15 PM" level="ERROR" thread="1"><message>Exception Caught: </message><properties><data name="log4jmachinename" value="IbrahimS-LPT" /><data name="log4japp" value="Log4net.exe" /><data name="log4net:Identity" value="" /><data name="log4net:UserName" value="SSS-PROCESS\ibrahims" /><data name="log4net:HostName" value="IbrahimS-LPT" /></properties><throwable>System.InvalidCastException: hhhhh ---> System.Exception: sub
--- End of inner exception stack trace ---</throwable><locationInfo class="Log4net.LoggingHelper" method="LogError" file="" line="0" /></event>
<event logger="SomeName2" time="4/16/2019 2:45:15 PM" level="ERROR" thread="1"><message>Exception Caught: </message><properties><data name="log4jmachinename" value="IbrahimS-LPT" /><data name="log4japp" value="Log4net.exe" /><data name="log4net:Identity" value="" /><data name="log4net:UserName" value="SSS-PROCESS\ibrahims" /><data name="log4net:HostName" value="IbrahimS-LPT" /></properties><throwable>System.InvalidCastException: hhhhh ---> System.Exception: sub
--- End of inner exception stack trace ---</throwable><locationInfo class="Log4net.LoggingHelper" method="LogError" file="" line="0" /></event>
when trying to open the file in xml format I got this error Unable to parse any XML input
but when add root element manually i am able to view
i need to be like this
<app>
<event logger="SomeName2" time="4/16/2019 2:45:15 PM" level="ERROR" thread="1"></event>
<event logger="SomeName2" time="4/16/2019 2:45:15 PM" level="ERROR" thread="1"></event>
</app>
class CustomXmlLayoutSchemaLog4j : XmlLayoutBase
{
#region Static Members
/// <summary>
/// The 1st of January 1970 in UTC
/// </summary>
private static readonly DateTime s_date1970 = new DateTime(1970, 1, 1);
#endregion
#region Constructors
/// <summary>
/// Constructs an XMLLayoutSchemaLog4j
/// </summary>
public CustomXmlLayoutSchemaLog4j() : base()
{
}
/// <summary>
/// Constructs an XMLLayoutSchemaLog4j.
/// </summary>
/// <remarks>
/// <para>
/// The <b>LocationInfo</b> option takes a boolean value. By
/// default, it is set to false which means there will be no location
/// information output by this layout. If the the option is set to
/// true, then the file name and line number of the statement
/// at the origin of the log statement will be output.
/// </para>
/// <para>
/// If you are embedding this layout within an SMTPAppender
/// then make sure to set the <b>LocationInfo</b> option of that
/// appender as well.
/// </para>
/// </remarks>
public CustomXmlLayoutSchemaLog4j(bool locationInfo) : base(locationInfo)
{
}
#endregion
#region Public Properties
/// <summary>
/// The version of the log4j schema to use.
/// </summary>
/// <remarks>
/// <para>
/// Only version 1.2 of the log4j schema is supported.
/// </para>
/// </remarks>
public string Version
{
get { return "1.2"; }
set
{
if (value != "1.2")
{
throw new ArgumentException("Only version 1.2 of the log4j schema is currently supported");
}
}
}
#endregion
/* Example log4j schema event
<event logger="first logger" level="ERROR" thread="Thread-3" timestamp="1051494121460">
<message><![CDATA[errormsg 3]]></message>
<NDC><![CDATA[third]]></NDC>
<MDC>
<data name="some string" value="some valuethird"/>
</MDC>
<throwable><![CDATA[java.lang.Exception: someexception-third
at org.apache.log4j.chainsaw.Generator.run(Generator.java:94)
]]></throwable>
<locationInfo class="org.apache.log4j.chainsaw.Generator"
method="run" file="Generator.java" line="94"/>
<properties>
<data name="log4jmachinename" value="windows"/>
<data name="log4japp" value="udp-generator"/>
</properties>
</event>
*/
/* Since log4j 1.3 the MDC has been combined into the properties element */
/// <summary>
/// Actually do the writing of the xml
/// </summary>
/// <param name="writer">the writer to use</param>
/// <param name="loggingEvent">the event to write</param>
/// <remarks>
/// <para>
/// Generate XML that is compatible with the log4j schema.
/// </para>
/// </remarks>
override protected void FormatXml(XmlWriter writer, LoggingEvent loggingEvent)
{
// Translate logging events for log4j
Header = "App";
// Translate hostname property
if (loggingEvent.LookupProperty(LoggingEvent.HostNameProperty) != null &&
loggingEvent.LookupProperty("log4jmachinename") == null)
{
loggingEvent.GetProperties()["log4jmachinename"] = loggingEvent.LookupProperty(LoggingEvent.HostNameProperty);
}
// translate appdomain name
if (loggingEvent.LookupProperty("log4japp") == null &&
loggingEvent.Domain != null &&
loggingEvent.Domain.Length > 0)
{
loggingEvent.GetProperties()["log4japp"] = loggingEvent.Domain;
}
// translate identity name
if (loggingEvent.Identity != null &&
loggingEvent.Identity.Length > 0 &&
loggingEvent.LookupProperty(LoggingEvent.IdentityProperty) == null)
{
loggingEvent.GetProperties()[LoggingEvent.IdentityProperty] = loggingEvent.Identity;
}
// translate user name
if (loggingEvent.UserName != null &&
loggingEvent.UserName.Length > 0 &&
loggingEvent.LookupProperty(LoggingEvent.UserNameProperty) == null)
{
loggingEvent.GetProperties()[LoggingEvent.UserNameProperty] = loggingEvent.UserName;
}
// Write the start element
writer.WriteStartElement("event");
writer.WriteAttributeString("logger", loggingEvent.LoggerName);
// Calculate the timestamp as the number of milliseconds since january 1970
//
// We must convert the TimeStamp to UTC before performing any mathematical
// operations. This allows use to take into account discontinuities
// caused by daylight savings time transitions.
TimeSpan timeSince1970 = loggingEvent.TimeStampUtc - s_date1970;
writer.WriteAttributeString("time", DateTime.Now.ToString());
writer.WriteAttributeString("level", loggingEvent.Level.DisplayName);
writer.WriteAttributeString("thread", loggingEvent.ThreadName);
// Append the message text
writer.WriteStartElement("message");
Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, this.InvalidCharReplacement);
writer.WriteEndElement();
object ndcObj = loggingEvent.LookupProperty("NDC");
if (ndcObj != null)
{
string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(ndcObj);
if (valueStr != null && valueStr.Length > 0)
{
// Append the NDC text
writer.WriteStartElement("NDC");
Transform.WriteEscapedXmlString(writer, valueStr, this.InvalidCharReplacement);
writer.WriteEndElement();
}
}
// Append the properties text
PropertiesDictionary properties = loggingEvent.GetProperties();
if (properties.Count > 0)
{
writer.WriteStartElement("properties");
foreach (System.Collections.DictionaryEntry entry in properties)
{
writer.WriteStartElement("data");
writer.WriteAttributeString("name", (string)entry.Key);
// Use an ObjectRenderer to convert the object to a string
string valueStr = loggingEvent.Repository.RendererMap.FindAndRender(entry.Value);
writer.WriteAttributeString("value", valueStr);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
string exceptionStr = loggingEvent.GetExceptionString();
if (exceptionStr != null && exceptionStr.Length > 0)
{
// Append the stack trace line
writer.WriteStartElement("throwable");
Transform.WriteEscapedXmlString(writer, exceptionStr, this.InvalidCharReplacement);
writer.WriteEndElement();
}
if (LocationInfo)
{
LocationInfo locationInfo = loggingEvent.LocationInformation;
writer.WriteStartElement("locationInfo");
writer.WriteAttributeString("class", locationInfo.ClassName);
writer.WriteAttributeString("method", locationInfo.MethodName);
writer.WriteAttributeString("file", locationInfo.FileName);
writer.WriteAttributeString("line", locationInfo.LineNumber);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
}
What you need to do is the next:
before this part of code:
// Write the start element
writer.WriteStartElement("event");
writer.WriteAttributeString("logger", loggingEvent.LoggerName);
You'll need to add this line:
writer.WriteStartElement("App");
Also, add a writer.WriteEndElement(); after the last one in you current code.
So your code will look like:
// Write the start element
writer.WriteStartElement("App");
writer.WriteStartElement("event");
writer.WriteAttributeString("logger", loggingEvent.LoggerName);
.
.
.
.
writer.WriteEndElement();
writer.WriteEndElement();

Programmatically get Summary comments at runtime

I'm looking for a way to programmatically get the summary portion of Xml-comments of a method in ASP.net.
I have looked at the previous related posts and they do not supply a way of doing so in a web environment.
I can not use any 3rd party apps and due to a web environment, Visual studio plugin's aren't much use either.
The closest thing I have found to a working solution was the JimBlackler project, but it only works on DLL's.
Naturally, something like 'supply .CS file, get XML documentation' would be optimal.
Current situation
I have a web-service and trying to dynamically generate documentation for it.
Reading the Methods, and properties is easy, but getting the Summary for each method is throwing me off a bit.
/// <summary>
/// This Is what I'm trying to read
/// </summary>
public class SomeClass()
{
/// <summary>
/// This Is what I'm trying to read
/// </summary>
public void SomeMethod()
{
}
}
A Workaround - Using reflection on Program.DLL/EXE together with Program.XML file
If you take a look at the sibling .XML file generated by Visual Studio you will see that there is a fairly flat hierarchy of /members/member.
All you have to do is get hold on each method from your DLL via MethodInfo object. Once you have this object you turn to the XML and use XPATH to get the member containing the XML documentation for this method.
Members are preceded by a letter. XML doc for methods are preceded by "M:" for class by "T:" etc.
Load your sibling XML
string docuPath = dllPath.Substring(0, dllPath.LastIndexOf(".")) + ".XML";
if (File.Exists(docuPath))
{
_docuDoc = new XmlDocument();
_docuDoc.Load(docuPath);
}
Use this xpath to get the member representing the method XML docu
string path = "M:" + mi.DeclaringType.FullName + "." + mi.Name;
XmlNode xmlDocuOfMethod = _docuDoc.SelectSingleNode(
"//member[starts-with(#name, '" + path + "')]");
Now scan childnodes for all the rows of "///"
Sometimes the /// Summary contains extra blanks, if this bothers use this to remove
var cleanStr = Regex.Replace(row.InnerXml, #"\s+", " ");
The XML summary isn't stored in the .NET assembly - it's optionally written out to an XML file as part of your build (assuming you're using Visual Studio).
Consequently there is no way to "pull out" the XML summaries of each method via reflection on a compiled .NET assembly (either .EXE or .DLL) - because the data simply isn't there for you to pull out. If you want the data, you'll have to instruct your build environment to output the XML files as part of your build process and parse those XML files at runtime to get at the summary information.
You could 'document' your method using the System.ComponentModel.DataAnnotations.DisplayAttribute attribute, e.g.
[Display(Name = "Foo", Description = "Blah")]
void Foo()
{
}
then use reflection to pull the description at runtime.
A deleted post, made by #OleksandrIeremenko, on this thread links to this article https://jimblackler.net/blog/?p=49 which was the basis for my solution.
Below is a modification of Jim Blackler's code making extension methods off the MemberInfo and Type objects and adding code that returns the summary text or an empty string if not available.
Usage
var typeSummary = typeof([Type Name]).GetSummary();
var methodSummary = typeof([Type Name]).GetMethod("[Method Name]").GetSummary();
Extension Class
/// <summary>
/// Utility class to provide documentation for various types where available with the assembly
/// </summary>
public static class DocumentationExtensions
{
/// <summary>
/// Provides the documentation comments for a specific method
/// </summary>
/// <param name="methodInfo">The MethodInfo (reflection data ) of the member to find documentation for</param>
/// <returns>The XML fragment describing the method</returns>
public static XmlElement GetDocumentation(this MethodInfo methodInfo)
{
// Calculate the parameter string as this is in the member name in the XML
var parametersString = "";
foreach (var parameterInfo in methodInfo.GetParameters())
{
if (parametersString.Length > 0)
{
parametersString += ",";
}
parametersString += parameterInfo.ParameterType.FullName;
}
//AL: 15.04.2008 ==> BUG-FIX remove “()” if parametersString is empty
if (parametersString.Length > 0)
return XmlFromName(methodInfo.DeclaringType, 'M', methodInfo.Name + "(" + parametersString + ")");
else
return XmlFromName(methodInfo.DeclaringType, 'M', methodInfo.Name);
}
/// <summary>
/// Provides the documentation comments for a specific member
/// </summary>
/// <param name="memberInfo">The MemberInfo (reflection data) or the member to find documentation for</param>
/// <returns>The XML fragment describing the member</returns>
public static XmlElement GetDocumentation(this MemberInfo memberInfo)
{
// First character [0] of member type is prefix character in the name in the XML
return XmlFromName(memberInfo.DeclaringType, memberInfo.MemberType.ToString()[0], memberInfo.Name);
}
/// <summary>
/// Returns the Xml documenation summary comment for this member
/// </summary>
/// <param name="memberInfo"></param>
/// <returns></returns>
public static string GetSummary(this MemberInfo memberInfo)
{
var element = memberInfo.GetDocumentation();
var summaryElm = element?.SelectSingleNode("summary");
if (summaryElm == null) return "";
return summaryElm.InnerText.Trim();
}
/// <summary>
/// Provides the documentation comments for a specific type
/// </summary>
/// <param name="type">Type to find the documentation for</param>
/// <returns>The XML fragment that describes the type</returns>
public static XmlElement GetDocumentation(this Type type)
{
// Prefix in type names is T
return XmlFromName(type, 'T', "");
}
/// <summary>
/// Gets the summary portion of a type's documenation or returns an empty string if not available
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static string GetSummary(this Type type)
{
var element = type.GetDocumentation();
var summaryElm = element?.SelectSingleNode("summary");
if (summaryElm == null) return "";
return summaryElm.InnerText.Trim();
}
/// <summary>
/// Obtains the XML Element that describes a reflection element by searching the
/// members for a member that has a name that describes the element.
/// </summary>
/// <param name="type">The type or parent type, used to fetch the assembly</param>
/// <param name="prefix">The prefix as seen in the name attribute in the documentation XML</param>
/// <param name="name">Where relevant, the full name qualifier for the element</param>
/// <returns>The member that has a name that describes the specified reflection element</returns>
private static XmlElement XmlFromName(this Type type, char prefix, string name)
{
string fullName;
if (string.IsNullOrEmpty(name))
fullName = prefix + ":" + type.FullName;
else
fullName = prefix + ":" + type.FullName + "." + name;
var xmlDocument = XmlFromAssembly(type.Assembly);
var matchedElement = xmlDocument["doc"]["members"].SelectSingleNode("member[#name='" + fullName + "']") as XmlElement;
return matchedElement;
}
/// <summary>
/// A cache used to remember Xml documentation for assemblies
/// </summary>
private static readonly Dictionary<Assembly, XmlDocument> Cache = new Dictionary<Assembly, XmlDocument>();
/// <summary>
/// A cache used to store failure exceptions for assembly lookups
/// </summary>
private static readonly Dictionary<Assembly, Exception> FailCache = new Dictionary<Assembly, Exception>();
/// <summary>
/// Obtains the documentation file for the specified assembly
/// </summary>
/// <param name="assembly">The assembly to find the XML document for</param>
/// <returns>The XML document</returns>
/// <remarks>This version uses a cache to preserve the assemblies, so that
/// the XML file is not loaded and parsed on every single lookup</remarks>
public static XmlDocument XmlFromAssembly(this Assembly assembly)
{
if (FailCache.ContainsKey(assembly))
{
throw FailCache[assembly];
}
try
{
if (!Cache.ContainsKey(assembly))
{
// load the docuemnt into the cache
Cache[assembly] = XmlFromAssemblyNonCached(assembly);
}
return Cache[assembly];
}
catch (Exception exception)
{
FailCache[assembly] = exception;
throw;
}
}
/// <summary>
/// Loads and parses the documentation file for the specified assembly
/// </summary>
/// <param name="assembly">The assembly to find the XML document for</param>
/// <returns>The XML document</returns>
private static XmlDocument XmlFromAssemblyNonCached(Assembly assembly)
{
var assemblyFilename = assembly.Location;
if (!string.IsNullOrEmpty(assemblyFilename))
{
StreamReader streamReader;
try
{
streamReader = new StreamReader(Path.ChangeExtension(assemblyFilename, ".xml"));
}
catch (FileNotFoundException exception)
{
throw new Exception("XML documentation not present (make sure it is turned on in project properties when building)", exception);
}
var xmlDocument = new XmlDocument();
xmlDocument.Load(streamReader);
return xmlDocument;
}
else
{
throw new Exception("Could not ascertain assembly filename", null);
}
}
}
You can use Namotion.Reflection NuGet package to get these information:
string summary = typeof(Foo).GetXmlDocsSummary();
You can look at https://github.com/NSwag/NSwag - source for nuget NSwag.CodeGeneration - it gets summary as well, usage
var generator = new WebApiAssemblyToSwaggerGenerator(settings);<br/>
var swaggerService = generator.GenerateForController("namespace.someController");<br/>
// string with comments <br/>
var swaggerJson = swaggerService.ToJson();
(try ILSPY decompiler against your dll, you check code and comments)
If you have access to the source code you're trying to get comments for, then you can use Roslyn compiler platform to do that. It basically gives you access to all the intermediary compiler metadata and you can do anything you want with it.
It's a bit more complicated than what other people are suggesting, but depending on what your needs are, might be an option.
It looks like this post has a code sample for something similar.

Is there any API for presenting normalized data after a query is made from linq?

For example Service Stack does this to with the Northwind database:
http://www.servicestack.net/ServiceStack.Northwind/customers/ALFKI?format=html
Is there anything that reads the database structure and relationships and output a report based on a primary id?
Obviously, I am looking into alternatives to servicestack.
I use LINQPad's .Dump() object visualizer for that. Download LINQPad from http://www.linqpad.net and reference the .exe in your project.
You will then have access to LINQPads .CreateXhtmlWriter() that can output a beautiful object graph visualization:
just by going:
var listOfItems = DataContext.Items.ToList();
listOfItems.Dump();
The following is not my code, but I cannot find the origin, so bear with me.
Use extension method to create the Xhtml dump and show it a browser:
public static class LinqPadExtensions
{
/// <summary>
/// Writes object properties to HTML
/// and displays them in default browser.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <param name="heading"></param>
public static void Dump<T>(
this T o,
string heading = null
)
{
string localUrl =
Path.GetTempFileName() + ".html";
using (
var writer =
LINQPad.Util.CreateXhtmlWriter(true)
)
{
if (!String.IsNullOrWhiteSpace(heading))
writer.Write(heading);
writer.Write(o);
File.WriteAllText(localUrl, writer.ToString());
}
Process.Start(localUrl);
}
}

how to add Child element in Existing XML

i have a Question i want to add Child Element in My Existing Xml How Can i Do this
please help me
Simple:
Load the XML into memory
Find the existing node where you want to append
Create the new element
Call something like XNode.AddAfterSelf
Save the result
The exact calls will depend on which library you use; personally I'd suggest using LINQ to XML if you possibly can (i.e. if you're using .NET 3.5 or higher) as it's much easier to use than the earlier APIs.
I'm using LINQ-to-XML, this seems easier to me and that is how I do it
First load it
/// <summary>
/// loads and returns the XML file with the given name
/// </summary>
/// <param name="modelHesapAdi"> name of the XML file to be returned</param>
/// <returns>returns the xml of given model hesap adı</returns>
public static XElement LoadXMLWithGivenModelHesapAdi(string modelHesapAdi, string xmlDirectory)
{
XElement modelsXmlFile = XElement.Load(xmlDirectory + modelHesapAdi + ".xml");
return modelsXmlFile;
}
Call the above method in another one
/// <summary>
/// gets a roommessage nood from CreateRoomMessageXElement
/// and adds it to the related room XML file and saves it
/// </summary>
/// <param name="modelHesapAdi">a string which has the name of the XML file to be changed</param>
/// <param name="incomingMemberHesapAdi">a string to be inserted to the xml file, which has the members name</param>
/// <param name="entranceTime"> a string for time, holds the member's entrance time</param>
public void AddMemberNodeToRoomMembersXMLWithGivenModelHesapAdiAndUyeHesapAdi(string modelHesapAdi,
string incomingMemberHesapAdi,
string entranceTime)
{
XElement modelsXmlFile = BAL.Models.Model.LoadXMLWithGivenModelHesapAdi(modelHesapAdi, xmlDirectory);//loads the xml
XElement roomMember = CreateRoomIncomingMemberXElement(incomingMemberHesapAdi, entranceTime);//creates child element and returns it
modelsXmlFile.Add(roomMember);//adds the child element
modelsXmlFile.Save(xmlDirectory + modelHesapAdi + ".xml");//saves the edited file
}
For child element creation
/// <summary>
/// creates and returns roommessage nood
/// </summary>
/// <param name="memberHesapAdi">the sender of the message</param>
/// <param name="message">sent message</param>
/// <param name="timeSent">the time when the message was sent</param>
/// <returns></returns>
private XElement CreateRoomIncomingMemberXElement(string memberHesapAdi, string entranceTime)
{
XElement roomMessage = new XElement("RoomMember",
new XElement("MemberHesapAdi", memberHesapAdi),
new XElement("Time", entranceTime));
return roomMessage;
}
In CreateRoomIncomingMemberXElement method you will create your own child element with your requirements, you will call it in AddMemberNodeToRoomMembersXMLWithGivenModelHesapAdiAndUyeHesapAdi and add it to the loaded file, then save it.
You can use the XDocument class to easily manipulate Xml in C#:
var doc = XDocument.Parse(yourXmlString); // Or XDocument.Load(pathToFile);
var childElement = new XElement("YourChildElementName", yourChildElementValue);
doc.Add(childElement);

Categories