Dynamics CRM plugin -Pre Operation Update - plugins

I created a plug-in that calculates the pricing of the quote based on custom fields whenever update done on the quote entity.I executed the plugin on pre-opertaion update of the quote entity.I tried to debbug my plugin, it retrives null values.For example the value of the field "edm_CashAmount" contains 5000 but the code retrieved null. Kindly advise on the below. Thanks in advance.
namespace CRMPlugins.Plugins
{
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Crm.Sdk.Messages;
public class PrequoteUpdate : Plugin
{
public PrequoteUpdate()
: base(typeof(PrequoteUpdate))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(20, "Update", "quote", new Action<LocalPluginContext>(ExecutePrequoteUpdate)));
}
protected void ExecutePrequoteUpdate(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
Entity entity = null;
if (localContext.PluginExecutionContext.InputParameters.Contains("Target") && localContext.PluginExecutionContext.InputParameters["Target"] is Entity)
{
entity = (Entity)localContext.PluginExecutionContext.InputParameters["Target"];
}
else
{
return;
}
decimal instotal = 0;
Quote quote = entity.ToEntity<Quote>();
using (GeneratedEntities orgContext = new GeneratedEntities(localContext.OrganizationService))
{
var installements = (from b in orgContext.edm_installementSet
where b.GetAttributeValue<Guid>("edm_quote") == quote.QuoteId
select b);
foreach (var c in installements)
{
if (c.edm_Amount != null)
{
instotal += (decimal)c.new_Decimal;
}
}
}
decimal cash = 0;
if (quote.edm_CashAmount != null)
{
cash = Convert.ToDecimal(quote.GetAttributeValue<Money>("edm_cashamount").Value);
}
decimal check = 0;
if (quote.edm_CheckAmount != null)
{
check = Convert.ToDecimal(quote.GetAttributeValue<Money>("edm_checkamount").Value);
}
decimal credit = 0;
if (quote.edm_CreditCardAmount != null)
{
credit = Convert.ToDecimal(quote.GetAttributeValue<Money>("edm_creditcardamount").Value);
}
decimal gift = 0;
if (quote.new_GiftCard != null)
{
gift = Convert.ToDecimal(quote.GetAttributeValue<Money>("new_giftcard").Value);
}
decimal total = 0;
if (quote.TotalLineItemAmount != null)
{
total = Convert.ToDecimal(quote.GetAttributeValue<Money>("totallineitemamount").Value);
}
decimal currentbalane = 0;
if (quote.edm_CurrentBalane != null)
{
currentbalane = Convert.ToDecimal(quote.GetAttributeValue<Money>("edm_currentbalane").Value);
}
decimal DiscAmount = 0;
if (quote.DiscountAmount != null)
{
DiscAmount = Convert.ToDecimal(quote.GetAttributeValue<Money>("discountamount").Value);
}
decimal totalafterdiscount = total - DiscAmount;
decimal tax = (totalafterdiscount * 10) / 100;
decimal totalwithvat = totalafterdiscount + tax;
decimal paidamount = cash + check + credit + gift + instotal;
decimal remainingamount = totalwithvat - paidamount;
quote["edm_cashamount_1"] = new Money(tax);
quote["edm_totaltax"] = new Money(tax);
quote["edm_paidamount"] = new Money(paidamount);
quote["edm_remainingamount"] = new Money(remainingamount);
quote["edm_total"] = new Money(totalwithvat);
quote["edm_totalinstallements"] = new Money(instotal);
quote["edm_checkamount_1"] = new Money(totalwithvat);
}
}
}

for update plugins, if the value has not been changed then it will not appear in the target entity. Therefore you should create a pre entity image an include these values, or you can create a post entity image to see the state of the entity after the changes will be applied

Related

Crm plugin update fails

I have created two new fields named "Price" for quote and quote product and I want to update the second every time I update the first.
Here is my code:
protected void ExecutePostAccountUpdateContacts(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
string oldPrice = "";
string newPrice = "";
IPluginExecutionContext context = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
var ServiceContext = new OrganizationServiceContext(service);
ITracingService tracingService = localContext.TracingService;
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
Entity preImageEntity = (context.PreEntityImages != null && context.PreEntityImages.Contains(this.preImageAlias)) ? context.PreEntityImages[this.preImageAlias] : null;
// get the post entity image
Entity postImageEntity = (context.PostEntityImages != null && context.PostEntityImages.Contains(this.postImageAlias)) ? context.PostEntityImages[this.postImageAlias] : null;
if (preImageEntity.Attributes.Contains("Price"))
{
oldPrice = (string)preImageEntity.Attributes["Price"];
}
if (postImageEntity.Attributes.Contains("Price"))
{
newPrice = (string)postImageEntity.Attributes["Price"];
}
if (newPrice != oldPrice)
{
try
{
//Create query to get the related contacts
var res = from c in ServiceContext.CreateQuery("Products")
where c["parentQuoteid"].Equals(entity.Id)
select c;
foreach (var c in res)
{
Entity e = (Entity)c;
e["Price"] = newPrice;
ServiceContext.UpdateObject(e);
}
ServiceContext.SaveChanges();
}
catch (FaultException ex)
{
throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
}
}
}
}
Although you haven't asked a question, your query isn't quite right. So I am assuming your plugin fails when querying for product with a parentquoteid.
Not all linq operators are implemented, also , pass the entity logical name to the create query as a parameter, so instead of Products, just product. There is no out of the box field called parentquoteid, are you missing your custom attribute prefix?
var res = from c in ServiceContext.CreateQuery("product")
where c.GetAttributeValue<Guid>("new_parentquoteid") == entity.Id
select c;

How to transfer Datagridview edit control to the next cell of the selected row when we press Enter Key

I am using this Code in dataGridView1_SelectionChanged and dataGridView1_CellEndEdit event. It works properly but when I press the enter Key firstly the edit control focus jumps on new row of selected column and then automatically goes back to the upper row and select the next cell. But I want to transfer directly to the next cell of the selected row.
For more details I attached a picture.
Please help me. I am trying a lot of logic for this.
Here my code
try
{
if (MouseButtons != 0) return;
if (celWasEndEdit != null && dataGridView1.CurrentCell != null)
{
// if we are currently in the next line of last edit cell
if (dataGridView1.CurrentCell.RowIndex == celWasEndEdit.RowIndex + 1 &&
dataGridView1.CurrentCell.ColumnIndex == celWasEndEdit.ColumnIndex)
{
int iColNew;
int iRowNew = 0;
if (celWasEndEdit.ColumnIndex >= dataGridView1.ColumnCount - 1)
{
iColNew = 0;
iRowNew = dataGridView1.CurrentCell.RowIndex;
}
//if we Edit the cell and press Enter the focus on the next cell
else
{
iColNew = celWasEndEdit.ColumnIndex + 1;
iRowNew = celWasEndEdit.RowIndex;
}
dataGridView1.CurrentCell = dataGridView1[iColNew, iRowNew];
}
}
celWasEndEdit = null;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Create an extended control derived from the DataGridView and override the ProcessDialogKey() method.
For additional information see here.
Test sources
User control:
using System.Windows.Forms;
namespace DGNextEdit
{
public class UpdatedDataGridView : DataGridView
{
protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == Keys.Enter)
{
var col = CurrentCell.ColumnIndex;
var row = CurrentCell.RowIndex;
if (col >= ColumnCount - 1 && row < RowCount - 1)
row++;
CurrentCell = this[col < ColumnCount - 1 ? col + 1 : 0, row];
return true;
}
return base.ProcessDialogKey(keyData);
}
}
}
Test form:
using System.Windows.Forms;
namespace DGNextEdit
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}
Test form code-behind:
namespace DGNextEdit
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGridView1 = new DGNextEdit.UpdatedDataGridView();
this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Column3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// dataGridView1
//
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.Column1,
this.Column2,
this.Column3});
this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGridView1.Location = new System.Drawing.Point(0, 0);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(465, 261);
this.dataGridView1.TabIndex = 0;
//
// Column1
//
this.Column1.HeaderText = "Column1";
this.Column1.Name = "Column1";
//
// Column2
//
this.Column2.HeaderText = "Column2";
this.Column2.Name = "Column2";
//
// Column3
//
this.Column3.HeaderText = "Column3";
this.Column3.Name = "Column3";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(465, 261);
this.Controls.Add(this.dataGridView1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private UpdatedDataGridView dataGridView1;
private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
private System.Windows.Forms.DataGridViewTextBoxColumn Column2;
private System.Windows.Forms.DataGridViewTextBoxColumn Column3;
}
}

Error while Inserting data in loop pne by one using Entity Framework

while inserting records in a loop
The property "id" is part of the object's key information and cannot be modified
secProductionRepository.Add(tblSecProduction);
this.SaveChanges();
CODE
Controller : This is the Controller code from where i am calling method of Repository . Adding data into repository and calling function to insert. i think i have to initialize it every time with new keyword. But where should i do that.
SingleMaster objGetXMLData = _iSingleService.GetXMLData();
if (objGetXMLData._tblSecDoorXMLData != null)
{
for (int totalCount = 0; totalCount < objGetXMLData._tblSecDoorXMLData.Count; totalCount++)
{
_tblSecDoorsProduction.txtTongue = singleDoorModel.txtTongue;
_tblSecDoorsProduction.numFibMesh = Convert.ToInt32(singleDoorModel.chkBoxFibreMesh);
_tblSecDoorsProduction.dteDesDate = DateTime.Now;
_iSingleDoorService.UpdatetblSecDoorsProduction(_tblSecDoorsProduction, "Insert");
}
}
Repository : Here i am inserting new row into the table
public void UpdatetblSecDoorsProduction(tblSecDoorsProduction tblSecDoorsProduction, string Message)
{
var secDoorsProductionRepository = Nuow.Repository<tblSecDoorsProduction>();
tblSecDoorsProduction alreadyAttached = null;
if (Message == "Insert")
{
secDoorsProductionRepository.Add(tblSecDoorsProduction);
Nuow.SaveChanges();
}
}
Create new object each time in the loop. Updated code here:
for (int totalCount = 0; totalCount < objGetXMLData._tblSecDoorXMLData.Count; totalCount++)
{
tblSecDoorsProduction _tblSecDoorsProduction = new tblSecDoorsProduction();
_tblSecDoorsProduction.txtTongue = singleDoorModel.txtTongue;
_tblSecDoorsProduction.numFibMesh = Convert.ToInt32(singleDoorModel.chkBoxFibreMesh);
_tblSecDoorsProduction.dteDesDate = DateTime.Now;
_iSingleDoorService.UpdatetblSecDoorsProduction(_tblSecDoorsProduction, "Insert");
}

create and update plugin in crm 2013 c#

I need to write plugin in CRM 2013 that do two thing:
If statecode = 3 and the field el_meeting_in_outlook_id is empty I
need to create a new appoitment.
If statecode = 3 and the field el_meeting_in_outlook_id is not empty
I need to update an existing appoitment.
This is what I wrote:
using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using tmura_Entity_Plugins;
namespace tmura_Entity__Plugins
{
public class postCreateUpdateServiceAppointment : Plugin
{
public postCreateUpdateServiceAppointment()
: base(typeof(postCreateUpdateServiceAppointment))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Create", null, new Action<LocalPluginContext>(ExecutePostCreate)));
base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Update", null, new Action<LocalPluginContext>(ExecutePostUpdate)));
}
private void ExecutePostCreate(LocalPluginContext obj)
{
Logger.WriteMessage("Enter ExecutePostCreate", CrmLogService.MessageLevel.Info, "");
if ((obj.PluginExecutionContext.InputParameters.Contains("Target")) && (obj.PluginExecutionContext.InputParameters["Target"] is Entity))
{
Entity serviceAppontment = (Entity)obj.PluginExecutionContext.InputParameters["Target"];
if (serviceAppontment.LogicalName != "serviceappointment")
return;
Logger.WriteMessage("", CrmLogService.MessageLevel.Info, "");
if ((serviceAppontment.Attributes.Contains("statecode")) || ((int)(serviceAppontment.Attributes["statecode"]) == 3) && (serviceAppontment.Attributes["el_meeting_in_outlook_id"] == null))
{
try
{
Entity appointment = new Entity("appointment");
appointment.Attributes.Add("subject", "Opened automatically");
appointment.Attributes.Add("description", "Just Checking");
appointment.Attributes.Add("el_serviceappointment_id", new EntityReference("serviceappointment", serviceAppontment.Id));
appointment.Attributes.Add("scheduledstart", DateTime.Now.AddDays(7));
appointment.Attributes.Add("scheduledend", DateTime.Now.AddDays(7));
obj.OrganizationService.Create(appointment);
}
catch (Exception ex)
{
Logger.WriteException(ex);
}
}
else if (((int)(serviceAppontment.Attributes["statecode"]) == 3) && (serviceAppontment.Attributes["el_meeting_in_outlook_id"] != null))
{
//TODO
}
}
}
}
}
I don't know what to write in the second section that is supposed to update the appointment. I tried to search the web but with no success.
Can you please help?
Where you have defined the registered events, you have to put "serviceappointment", that is the entity logical name, instead of null.
Then replace: (serviceAppontment.Attributes.Contains("statecode")) || ((int)(serviceAppontment.Attributes["statecode"]) == 3) by (serviceAppontment.Attributes.Contains("statecode")) && ((OptionSetValue)(serviceAppontment.Attributes["statecode"]).Value == 3), because the field "statecode" is an OptionSet. Also replace the || by &&, because when serviceAppontment.Attributes.Contains("statecode")) is false, ((OptionSetValue)(serviceAppontment.Attributes["statecode"]).Value will throw an NullReferenceException.
To update an existing appointment, looks like there is an lookup in appointment entity to serviceappointment entity. So, you have to retrieve all the appointments related with the serviceappointment. You can use this query:
QueryExpression queryExp = new QueryExpression
{
EntityName = "appointment",
ColumnSet = new ColumnSet("subject", "description", "scheduledstart", "scheduledend"),
Criteria = new FilterExpression
{
Conditions = { new ConditionExpression("el_serviceappointment_id", ConditionOperator.Equal, serviceAppontment.Id) }
}
};
EntityCollection collection = obj.OrganizationService.RetrieveMultiple(queryExp);
if (collection.Entities.Count > 0)
{
// now that you have all the appointments related with the serviceappoitement
// you can update de any appointment you want
obj.OrganizationService.Update(appointment);
}
To update your record with a value in a lookup field in serviceappoitnment to may retrieve the serviceappoitment record Entity svcApp = obj.OrganizationService.Retrieve(serviceAppontment.LogicalName, serviceAppontment.Id, new ColumnSet("<lookup_field_in_serviceappoitnment>");
You need to add to the collumnset in the query expression the attribute requiredattendees, and then update the appoitment
if(appointment.Attributes.Contains("requiredattendees") == true)
{
appointment.Attributes["requiredattendees"] = svcApp.Attributes["<lookup_field_in_serviceappoitnment>"];
}
else
{
appointment.Attributes.Add("requiredattendees", svcApp.Attributes["<lookup_field_in_serviceappoitnment>");
}

EF - I can not assign values to foreign keys via Create

I'm a fairly green beginner (1 year training altogether) in C#.
My assignment was to create tables in a DB through Visual Studio 2010 - I did via EF. Now I want to write a simple Console program to fill those tables with values. In SQL MS they look right. In the last few lines of my code, I get the error msg that the CreateBestellung()-method only takes two arguments though. That'll be the two columns I created in this table. But how do I assign values to the foreign key fields? Couldn't find anything about this so far.
private static void bestellungAnlegen(playgroundEntities context)
{
Console.Clear();
Console.WriteLine("Neue Bestellung anlegen");
int kdId = -1;
int wrId = -1;
int anzahl = 0;
int id = -1;
// Validierung der Werte
do
{
Console.Write("Kunden ID: ");
if (int.TryParse(Console.ReadLine(), out kdId))
{
kdId = int.Parse(Console.ReadLine());
}
} while (kdId == -1);
do
{
Console.Write("Waren ID: ");
if (int.TryParse(Console.ReadLine(), out kdId))
{
kdId = int.Parse(Console.ReadLine());
}
} while (wrId == -1);
do
{
Console.Write("Anzahl: ");
if (int.TryParse(Console.ReadLine(), out anzahl))
{
if (anzahl >= 0)
{
anzahl = int.Parse(Console.ReadLine());
}
else anzahl = 0;
}
} while (anzahl == 0);
Bestellung neueBestellung =
Bestellung.CreateBestellung(id, anzahl, kdId, wrId);
context.Bestellungen.AddObject(neueBestellung);
}
This can only be a wild (but educated) guess. I think the method call should be
Bestellung neueBestellung = Bestellung.CreateBestellung(id, anzahl);
followed by
neueBestellung.kdId = kdId;
neueBestellung.wrId = wrId;