I am developing an extension to Acumatica and one of the things I would like to do is execute Confirm Shipment and Prepare Invoice actions on the Process Shipments screen from code. I also will need to release the invoice.
To simplify the discussion, at a certain point in the code I will have a shipment in the cache and a pointer to the SOShipmentEntry graph:
SOShipment soShipment = soShipmentGraph.Document.Search<SOShipment.shipmentNbr>(shipmentNbr);
At different points I would like to be able to confirm the shipment, prepare the invoice, and release the invoice. I have done a lot of digging and I have found the ConfirmShipment method, but I get errors trying to call it - shipment counters corrupted. I called it with:
SOOrder soOrder = PXSelect<SOOrder, Where<SOOrder.orderNbr,
Equal<Required<SOOrder.orderNbr>>>>.Select(this, orderNbr);
soOrderGraph.Document.Current = soOrder;
soShipmentGraph.ConfirmShipment(soOrderGraph, soShipment);
Studio compiled it, but I get the corrupted counters exception when it runs. There is some code in the PXAction logic in SOShipmentEntry that I must need. I just don't know how to call the action directly from code.
Any help is appreciated.
Calling the function directly like you are doing is the most obvious choice however we must understand how the the actions work in the graph SOShipmentEntry. By looking at the source code we can understand that the PXAction called is the following:
public PXAction<SOShipment> action;
[PXUIField(DisplayName = "Actions", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXButton]
protected virtual IEnumerable Action(PXAdapter adapter,
[PXInt]
[PXIntList(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, new string[] { "Confirm Shipment", "Create Invoice", "Post Invoice to IN", "Apply Assignment Rules", "Correct Shipment", "Create Drop-Ship Invoice", "Print Labels", "Get Return Labels", "Cancel Return" })]
int? actionID,
[PXString()]
string ActionName
)
By digging further in the function we can notice that what is executed when actionID=1 is much more than simply calling public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder):
case 1:
{
List<object> _persisted = new List<object>();
foreach (SOOrder item in Caches[typeof(SOOrder)].Updated)
{
_persisted.Add(item);
}
Save.Press();
PXAutomation.CompleteAction(this);
PXLongOperation.StartOperation(this, delegate()
{
SOShipmentEntry docgraph = PXGraph.CreateInstance<SOShipmentEntry>();
SOOrderEntry orderentry = PXGraph.CreateInstance<SOOrderEntry>();
orderentry.Caches[typeof(SiteStatus)] = docgraph.Caches[typeof(SiteStatus)];
orderentry.Caches[typeof(LocationStatus)] = docgraph.Caches[typeof(LocationStatus)];
orderentry.Caches[typeof(LotSerialStatus)] = docgraph.Caches[typeof(LotSerialStatus)];
orderentry.Caches[typeof(ItemLotSerial)] = docgraph.Caches[typeof(ItemLotSerial)];
PXCache cache = orderentry.Caches[typeof(SOShipLineSplit)];
cache = orderentry.Caches[typeof(INTranSplit)];
orderentry.Views.Caches.Remove(typeof(SiteStatus));
orderentry.Views.Caches.Remove(typeof(LocationStatus));
orderentry.Views.Caches.Remove(typeof(LotSerialStatus));
orderentry.Views.Caches.Remove(typeof(ItemLotSerial));
PXAutomation.StorePersisted(docgraph, typeof(SOOrder), _persisted);
foreach (SOOrder item in _persisted)
{
PXTimeStampScope.PutPersisted(orderentry.Document.Cache, item, item.tstamp);
}
foreach (SOShipment shipment in list)
{
try
{
if (adapter.MassProcess) PXProcessing<SOShipment>.SetCurrentItem(shipment);
if (shipment.Operation != SOOperation.Receipt)
docgraph.ShipPackages(shipment);
docgraph.ConfirmShipment(orderentry, shipment);
}
catch (Exception ex)
{
if (!adapter.MassProcess)
{
throw;
}
PXProcessing<SOShipment>.SetError(ex);
}
}
});
}
We can understand that the best way to call it will be to simulate clicking on the button Confirm Shipment that was generated by the framework and will basically call the PXAction<SOOrder> action with the argument actionID=1. To do so we will need to do a bit of gymnastic. Here's an example where we add a button Confirm Shipment to the Shipments grid in the page Sales Order:
namespace PX.Objects.SO
{
public class SOOrderEntry_Extension : PXGraphExtension<SOOrderEntry>
{
public PXAction<SOOrder> confirmShipment;
[PXUIField(DisplayName = "Confirm Shipment")]
[PXButton]
protected virtual IEnumerable ConfirmShipment(PXAdapter adapter)
{
var soOrderShip = Base.shipmentlist.Current;
if ( soOrderShip != null)
{
var graph = PXGraph.CreateInstance<SOShipmentEntry>();
//We are recreating an adapter like the framework would do.
var a = new PXAdapter(graph.Document)
{
Searches = new object[] { soOrderShip.ShipmentNbr }
};
//Note: Confirm Shipment is Action 1 :
a.Arguments.Add("actionID", 1);
PXLongOperation.StartOperation(Base, () => { foreach (SOShipment soShipment in graph.action.Press(a)); });
}
return adapter.Get();
}
protected virtual void SOOrderShipment_RowSelected(PXCache sender, PXRowSelectedEventArgs e, PXRowSelected del)
{
var shipment = (SOOrderShipment)e.Row;
if (shipment != null)
confirmShipment.SetEnabled(!shipment.Confirmed.GetValueOrDefault());
del(sender, e);
}
}
}
If you want to test the whole project here's the customization project XML
<Customization level="0" description="">
<Page path="~/pages/so/so301000.aspx" pageSource="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">
<PXDataSource ID="ds" ParentId="phDS_ds" TypeFullName="PX.Web.UI.PXDataSource">
<Children Key="CallbackCommands">
<AddItem>
<PXDSCallbackCommand TypeFullName="PX.Web.UI.PXDSCallbackCommand">
<Prop Key="Name" Value="ConfirmShipment" />
<Prop Key="Visible" Value="false" />
<Prop Key="DependOnGrid" Value="grid5" />
<Prop Key="CommitChanges" Value="true" />
</PXDSCallbackCommand>
</AddItem>
<PXDSCallbackCommand Name="CalculateFreight" OriginalIndex="19" />
</Children>
</PXDataSource>
<PXGrid ID="grid5" ParentId="phG_tab_Items#7_grid5" TypeFullName="PX.Web.UI.PXGrid">
<Children Key="ActionBar.CustomItems">
<AddItem>
<PXToolBarButton TypeFullName="PX.Web.UI.PXToolBarButton">
<Prop Key="Text" Value="Confirm Shipment" />
<Prop Key="Tooltip" Value="Confirm Shipment" />
<Prop Key="CommandSourceID" Value="ds" />
<Prop Key="CommandName" Value="ConfirmShipment" />
</PXToolBarButton>
</AddItem>
</Children>
</PXGrid>
<PXGridColumn DataField="ShipmentNbr" ParentId="phG_tab_Items#7_grid5_Levels#0_Columns#0" TypeFullName="PX.Web.UI.PXGridColumn">
<Prop Key="CommitChanges" />
<Prop Key="LinkCommand" />
</PXGridColumn>
</Page>
<Graph ClassName="SOOrderEntry" Source="#CDATA" IsNew="True" FileType="ExistingGraph">
<CDATA name="Source"><![CDATA[using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Avalara.AvaTax.Adapter;
using Avalara.AvaTax.Adapter.TaxService;
using PX.CCProcessingBase;
using PX.Common;
using PX.Data;
using PX.Objects.AP;
using PX.Objects.AR;
using PX.Objects.CA;
using PX.Objects.CM;
using PX.Objects.CR;
using PX.Objects.CS;
using PX.Objects.DR;
using PX.Objects.EP;
using PX.Objects.GL;
using PX.Objects.IN;
using PX.Objects.PM;
using PX.Objects.PO;
using PX.Objects.TX;
using AvaMessage = Avalara.AvaTax.Adapter.Message;
using POLine = PX.Objects.PO.POLine;
using POOrder = PX.Objects.PO.POOrder;
using System.Threading.Tasks;
using CRLocation = PX.Objects.CR.Standalone.Location;
using PX.Objects;
using PX.Objects.SO;
namespace PX.Objects.SO
{
public class SOOrderEntry_Extension : PXGraphExtension<SOOrderEntry>
{
public PXAction<SOOrder> confirmShipment;
[PXUIField(DisplayName = "Confirm Shipment")]
[PXButton]
protected virtual IEnumerable ConfirmShipment(PXAdapter adapter)
{
var soOrderShip = Base.shipmentlist.Current;
if ( soOrderShip != null)
{
var graph = PXGraph.CreateInstance<SOShipmentEntry>();
//We are recreating an adapter like the framework would do.
var a = new PXAdapter(graph.Document)
{
Searches = new object[] { soOrderShip.ShipmentNbr }
};
//Note: Confirm Shipment is Action 1 :
a.Arguments.Add("actionID", 1);
PXLongOperation.StartOperation(Base, () => { foreach (SOShipment soShipment in graph.action.Press(a)); });
}
return adapter.Get();
}
protected virtual void SOOrderShipment_RowSelected(PXCache sender, PXRowSelectedEventArgs e, PXRowSelected del)
{
var shipment = (SOOrderShipment)e.Row;
if (shipment != null)
confirmShipment.SetEnabled(!shipment.Confirmed.GetValueOrDefault());
del(sender, e);
}
}
}]]></CDATA>
</Graph>
</Customization>
I also came through this shipment counter corrupted.
Auto confirm shipment when create shipment from Sales Order by Automation Step
The answer from Hybridzz worked for me, you can check it out.
Related
We’re using file synchronization to send payment batch files to an external site. File Synchronization only works on a per file basis so we have set up one file that our export scenario will populate.
Because we need every version of this file to be sent to the external site, I need to make sure that every revision of the file is synchronized.
My thought was to override the Export button on Batch Payments (AP305000) to call the Process All Files action, using the Export File operation, on the File Synchronization screen. The challenge is that I can’t see to find the name of the graph to instantiate to access that business object.
Here is where I’m at:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Api;
using PX.Data;
using PX.Data.WorkflowAPI;
using PX.Objects.AP;
using PX.Objects.AR;
using PX.Objects.CM;
using PX.Objects.Common.Extensions;
using PX.Objects.CR;
using PX.Objects.CS;
using PX.Objects.GL;
using PX.Objects.AP.MigrationMode;
using PX.Objects;
using PX.Objects.CA;
using PX.Objects.SM;
namespace PX.Objects.CA
{
public class CABatchEntry_Extension : PXGraphExtension<CABatchEntry>
{
[PXOverride]
public virtual IEnumerable Export(PXAdapter adapter)
{
Base.export.Press(adapter);
//Challenge is here
SynchronizationProcess docgraph = PXGraph.CreateInstance<SynchronizationProcess>();
foreach (var action in (docgraph.action.GetState(null) as PXButtonState).Menus)
{
if (action.Command == "Process All Files")
{
PXAdapter adapter2 = new PXAdapter(new DummyView(docgraph, docgraph.Document.View.BqlSelect, new List<object> { docgraph.Document.Current }));
adapter2.Menu = action.Command;
docgraph.action.PressButton(adapter2);
TimeSpan timespan;
Exception ex;
while (PXLongOperation.GetStatus(docgraph.UID, out timespan, out ex) == PXLongRunStatus.InProcess)
{ }
break;
}
}
return adapter.Get();
}
internal class DummyView : PXView
{
List<object> _Records;
internal DummyView(PXGraph graph, BqlCommand command, List<object> records)
: base(graph, true, command)
{
_Records = records;
}
public override List<object> Select(object[] currents, object[] parameters, object[] searches, string[] sortcolumns, bool[] descendings, PXFilterRow[] filters, ref int startRow, int maximumRows, ref int totalRows)
{
return _Records;
}
}
}
}
You can write your own PXLongOperation which will invoke the Processing Delegate the same way that page does, like below. Then you can use PXLongOperation.WaitCompletion(this.Base.UID) to wait till the process is completed and then do any other actions that you need to do.
public PXAction<SOOrder> RunSynchronization;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Sync Files")]
protected IEnumerable runSynchronization(PXAdapter adapter)
{
PXLongOperation.StartOperation(this.Base, () =>
{
SynchronizationProcess docgraph = PXGraph.CreateInstance<SynchronizationProcess>();
docgraph.filter.SetValueExt<SynchronizationFilter.operation>(docgraph.filter.Current,"U"); //U - export D - import
var records = docgraph.SelectedFiles.Select().RowCast<UploadFileWithIDSelector>().ToList();
docgraph.SelectedFiles.GetProcessDelegate().DynamicInvoke(records);
});
return adapter.Get();
}
Very unfamiliar with Acumatica, I am trying to make a button clickable that I configured on the Employee Time Card screen. I want it to call a method when clicked but I have been unsuccessful.
Here is my the screen. The button is labeled PUNCH CARD.
Made some changes:
When I click on the PUNCH CARD button I do see a POST back to the server: https://dev.domain.tld/db/(W(20))/pages/ep/ep305000.aspx?PopupPanel=Inline&HideScript=On&TimeCardCD=TC00000001
I think I should be seeing some exception response on the screen but I see nothing.
Here is the aspx code. I don't know what to put in the DependOnGrid attribute. I just copied what was on Yuri Zaletskyy's blog. Is this always set to this or is there something specific to the site / page I am working with? If so how do I determine what to put here?
<px:PXToolBarButton Text="Punch Card" Visible="True" DependOnGrid="grdJiraProjects">
<AutoCallBack Target="" Enabled="True" Command="punchCard">
<Behavior CommitChanges="True" /></AutoCallBack>
<PopupCommand>
<Behavior CommitChanges="True" />
</PopupCommand></px:PXToolBarButton>
C# Code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Common;
using PX.Data;
using PX.Objects.CR;
using PX.Objects.CS;
using PX.Objects.IN;
using PX.Objects.CT;
using PX.Objects.PM;
using PX.Objects.GL;
using System.Diagnostics;
using System.Globalization;
using PX.SM;
using PX.TM;
using PX.Web.UI;
using Branch = PX.Objects.GL.Branch;
using System.Text;
using PX.Objects.GL.FinPeriods.TableDefinition;
using PX.Objects.GL.FinPeriods;
using PX.Objects;
using PX.Objects.EP;
namespace TimeTracking
{
public class TimeCardMaint_Extension : PXGraphExtension<PX.Objects.EP.TimeCardMaint>
{
public PXSelect<PMTimeActivity> PMTimeActivity;
public PXAction<EPTimeCard> PunchCard;
#region Event Handlers
protected void EPTimecardDetail_UsrPIXIClockIn_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (PMTimeActivity)e.Row;
var rows = row.GetExtension<PMTimeActivityExt>();
updateTotalHours(cache, rows, row);
}
protected void EPTimecardDetail_UsrPIXIClockOut_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (PMTimeActivity)e.Row;
var rows = row.GetExtension<PMTimeActivityExt>();
updateTotalHours(cache, rows, row);
}
#endregion
public void punchCard()
{
throw new PXException("You Clicked Punch Time Card on Action Bar");
}
public void updateTotalHours(PXCache cache, PMTimeActivityExt rows, PMTimeActivity row)
{
if (rows.UsrPIXIClockIn != null && rows.UsrPIXIClockOut != null)
{
DateTime dtClockIn = DateTime.Parse(rows.UsrPIXIClockIn.ToString());
DateTime dtClockOut = DateTime.Parse(rows.UsrPIXIClockOut.ToString());
double total = (dtClockOut - dtClockIn).TotalHours;
rows.UsrPIXITotalHours = (decimal) total;
}
}
}
}
One common catch that results in the button action event handler not being called is using the wrong DAC for the action generic type parameter.
Make sure the action generic type matches the graph primary DAC. In your case this would be EPTimeCard:
public PXAction<EPTimeCard> PunchCard;
Do you have a Graph Extension?
That's where you should put the action event handler for the button.
In your case TimeCardMaint is the graph of the employee time card screen:
using PX.Data;
using PX.Web.UI;
using System.Collections;
namespace PX.Objects.EP
{
public class TimeCardMaint_Extension : PXGraphExtension<TimeCardMaint>
{
public PXAction<EPTimeCard> PunchCard;
[PXButton]
[PXUIField(DisplayName = "Punch Card")]
public virtual IEnumerable punchCard(PXAdapter adapter)
{
// This is where you handle button click event
return adapter.Get();
}
}
}
There is something special about the button you added. It is located in a grid toolbar. It's often the case that you want grid toolbar actions to operate on the currently selected line. For that to work you need to declare the action in ASP file and set it's DependOnGrid property:
This is explained in more details here:
http://blog.zaletskyy.com/dependongrid-in-acumatica-or-how-to-get-currently-selected-record-in-grid
This link could help you too:
http://blog.zaletskyy.com/add-button-to-grid-in-acumatica
Once everything is setup you could then access the currently selected record in the grid from your action event handler like this:
[PXButton]
[PXUIField(DisplayName = "Punch Card")]
public virtual IEnumerable punchCard(PXAdapter adapter)
{
EPTimeCardDetail row = Base.Activities.Current as EPTimeCardDetail;
if (row != null)
{
// Presumably do some Punch Card action on selected row from Details tab Activities grid
}
return adapter.Get();
}
I have a custom button on CR306000 to try to print current loaded case information by calling one customized report. Navigation URL current set to:
~/Frames/ReportLauncher.aspx?ID=Inquirycase.rpx&CASEID=####
I will need to have custom programming to assign current case ID to replace "####", but don't know where and how to reference that custom button and modify its property. Please help. Thanks.
You could add a report parameter called 'CaseID' to your report and call it using the following code using an AEF extension like this:
public class CRCaseMaintExtension : PXGraphExtension<CRCaseMaint>
{
public override void Initialize()
{
base.Initialize();
//if adding to an existing menu button do that here...
// Example:
//Base.Inquiry.AddMenuAction(this.CustomReportButton);
}
public PXAction<CRCase> CustomReportButton;
[PXButton]
[PXUIField(DisplayName = "Custom Report", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
public virtual IEnumerable customReportButton(PXAdapter adapter)
{
if (Base.Case.Current != null)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters["CaseID"] = Base.Case.Current.CaseID.ToString();
//enter in your report id/number here
string reportNumber = "Inquirycase";
//opens the report using the defined parameters
throw new PXReportRequiredException(parameters, reportNumber, "Custom Report");
}
return adapter.Get();
}
}
I have not tested the above but this should get you most of the way there.
I am trying to add an option under Actions in Acumatica on the Checks & Payment screen AP302000. See below what I am trying to achieve:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using PX.Common;
using PX.Data;
using PX.Objects.CM;
using PX.Objects.CA;
using PX.Objects.CS;
using PX.Objects.GL;
using PX.Objects.CR;
using PX.Objects;
using PX.Objects.AP;
namespace PX.Objects.AP
{
public class APPaymentEntry_Extension:PXGraphExtension<APPaymentEntry>
{
#region Event Handlers
public PXAction<APPayment> ShowURL;
[PXUIField(DisplayName = "Print Remittance")]
[PXButton]
protected virtual void showURL()
{
APPayment doc = Document.Current;
if (doc.RefNbr != null) {
throw new PXReportRequiredException(doc.RefNbr, "AP991000", null);
}
}
#endregion
}
}
This is however telling me that there is no definition and no extension method for 'APPayment'. Can someone please walk me through how to achieve what I am trying to do?
Note that the report has only 1 parameter (RefNbr)
Thanks,
G
To Add a new Action in existing Actions Menu, you should override the Initialize() method and use AddMenuAction.
public class APPaymentEntry_Extension : PXGraphExtension<APPaymentEntry>
{
public override void Initialize()
{
Base.action.AddMenuAction(ShowURL);
}
public PXAction<APPayment> ShowURL;
[PXUIField(DisplayName = "Print Remittance")]
[PXButton]
protected virtual void showURL()
{
APPayment doc = Base.Document.Current;
if (doc.RefNbr != null)
{
throw new PXReportRequiredException(doc, "AP991000", null);
}
}
}
Document.Current should be accessed as Base.Document.Current in Extensions. You need to pass the DAC as first parameter in PXReportRequiredException if DAC has the appropriate parameter value. Alternatively, you can build parameters and pass it to PXReportRedirectException.
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters["ParameterName1"] = <Parameter Value>;
...
throw new PXReportRequiredException(parameters, <reportID>, "Report")
I am trying to create a custom workflow activity which gives me the list of recipients that I am storing in list. But once I deploy and start the workflow nothing is happening, not even log messages are coming. So i tried to debug the code but breakpoints are not set and I am getting the error "The Breakpoint will not currently be hit. No symbols have been loaded for this document." Can anyone please help me to deal with this issue.
Below are the steps I have followed in creating this activity.
1. created a workflow activity library.
(please find my code file attached)
added .dll to GAC
updated web.config and WSS.actions files.
Now I see the action in designer, so i have created a workflow using designer.
strted the workflow manually on an item.
Here nothing is happening, not even an error. Please let me know if you need any further information.
Please find the code below.
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using System.Diagnostics;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
namespace CustomWorkflowActivityLibrary
{
public partial class CustomWorkflowActivity: SequenceActivity
{
SPList _list;
private EventLog _log;
SPFieldUserValueCollection objUserFieldValueCol;
string semailsettingKeyword1;
string semailsettingKeyword2;
public CustomWorkflowActivity()
{
InitializeComponent();
}
public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(CustomWorkflowActivity));
[DescriptionAttribute("__Context")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get { return ((WorkflowContext)(base.GetValue(CustomWorkflowActivity.__ContextProperty))); }
set { base.SetValue(CustomWorkflowActivity.__ContextProperty, value); }
}
public static DependencyProperty ListIdProperty = DependencyProperty.Register("ListId", typeof(string), typeof(CustomWorkflowActivity));
[DescriptionAttribute("ListId")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public string ListId
{
get { return ((string)(base.GetValue(CustomWorkflowActivity.ListIdProperty))); }
set { base.SetValue(CustomWorkflowActivity.ListIdProperty, value); }
}
public static DependencyProperty ListItemProperty = DependencyProperty.Register("ListItem", typeof(int), typeof(CustomWorkflowActivity));
[DescriptionAttribute("ListItem")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public int ListItem
{
get { return ((int)(base.GetValue(CustomWorkflowActivity.ListItemProperty))); }
set { base.SetValue(CustomWorkflowActivity.ListItemProperty, value); }
}
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
_log = new EventLog("Add Description");
_log.Source = "Share Point Workflows";
try
{
//Execute method as a elevated method
SPSecurity.CodeToRunElevated elevatedExecuteMethod = new SPSecurity.CodeToRunElevated(ExecuteMethod);
SPSecurity.RunWithElevatedPrivileges(elevatedExecuteMethod);
}
catch (Exception ex)
{
_log.WriteEntry("Error" + ex.Message.ToString(), EventLogEntryType.Error);
}
return ActivityExecutionStatus.Closed;
}
private void ExecuteMethod()
{
try
{
//retrieveing the Site object
SPSite _site = new SPSite(__Context.Site.Url);
//retrieveing the Web object
SPWeb _web = (SPWeb)(__Context.Web);
//retrieveing the list object
_list = _web.Lists[new Guid(this.ListId)];
//retrieveing the list item object
SPListItem _listItem = _list.GetItemById(this.ListItem);
_site.AllowUnsafeUpdates = true;
_web.AllowUnsafeUpdates = true;
string semailsubject = _listItem["E-Mail Subject"].ToString();
string semailfrom = _listItem["emailfrom"].ToString();
_log = new EventLog("get vendor info");
_log.WriteEntry("semailsubject");
_log.WriteEntry("semailfrom");
/* _listItem.Update();
_list.Update();
_site.AllowUnsafeUpdates = false;
_web.AllowUnsafeUpdates = false;*/
using (SPSite mysite = new SPSite("http://dlglobaltest.dl.com/Admin/IT/Application%20Development%20Group/LibraryEmailDistribution"))
{
using (SPWeb myweb = mysite.OpenWeb())
{
SPList settingsList = myweb.Lists["EmailDistributionSettings"];
SPQuery oQuery = new SPQuery();
oQuery.Query = "<Where><Eq><FieldRef Name='Sender' /><Value Type='Text'>" + semailfrom + "</Value></Eq></Where>";
SPListItemCollection ColListItems = settingsList.GetItems(oQuery);
foreach (SPListItem oListItem in ColListItems)
{
semailsettingKeyword1 = oListItem["Keyword1"].ToString();
semailsettingKeyword2 = oListItem["Keyword2"].ToString();
//SPFieldUserValue objUserFieldValue = new SPFieldUserValue(myweb, oListItem["Recipients"].ToString());
if ((semailsubject.Contains(semailsettingKeyword1)) || (semailsubject.Contains(semailsettingKeyword2)))
{
objUserFieldValueCol = new SPFieldUserValueCollection(myweb, oListItem["Recipients"].ToString());
_log = new EventLog(objUserFieldValueCol.ToString());
}
}
}
}
}
catch (Exception ex)
{ }
}
}
}
Web.Config:
<authorizedType Assembly="CustomWorkflowActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a95e146fc1062337" Namespace="CustomWorkflowActivityLibrary" TypeName="*" Authorized="True" />
WSS.Actions:
<Action Name="Get Recipients"
ClassName="CustomWorkflowActivityLibrary.CustomWorkflowActivity"
Assembly="CustomWorkflowActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a95e146fc1062337"
AppliesTo="all" Category="Custom">
<RuleDesigner Sentence="Get Recipients for %1 ">
<FieldBind Field="ListId,ListItem" Text="this list" Id="1" DesignerType="ChooseListItem" />
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
<Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In" />
</Parameters>
</Action>
Thanks,
I am not sure if this will help but you could try changing the following line in your code from this:
SPSecurity.RunWithElevatedPrivileges(elevatedExecuteMethod);
To this:
SPSecurity.RunWithElevatedPrivileges(delegate(){
ExecuteMethod();
});
Another shot-in-the-dark reply:
Try changing the class you're inheriting ( http://msdn.microsoft.com/en-us/library/ms173149(v=VS.80).aspx ) from SequenceActivity to Activity (SequenceActivity inherits from CompositeActivity, which itself inherits from Activity. See: http://msdn.microsoft.com/en-us/library/system.workflow.activities.sequenceactivity(v=VS.90).aspx )
If that doesn't work, try removing your constructor entirely. You should be able to use the base (Sequence)Activity constructor (since you're inheriting the class, not implementing it)
Hope that helps...