Acumatica API: Using CR303000.Actions.ConverToCustomer - acumatica

I'm trying to use the Acumatica API to convert a Business Account to a Customer on Acumatica 5.20.2067. The code I'm using is based on converting a Lead to a Business Account. Converting a Business Account to a Customer seems simpler than converting a Lead because converting a Business Account does not pop up a dialog box. However, I've tried it two ways and one produces an error and the other creates a completely separate Customer record instead of converting the existing Business Account.
Based on the code in the other post about converting a Lead, here is the code that I think should work:
Public Function ConvertBusinessAccountToCustomer(ByVal baID As String, ByVal firstName As String, ByVal LastName As String)
Dim CR303000 As CR303000Content = m_context.CR303000GetSchema()
m_context.CR303000Clear()
Dim AR303000 As AR303000Content = m_context.AR303000GetSchema()
m_context.AR303000Clear()
' call the Action to convert the BA to a Customer
Dim baKeyVal As Value = CreateValue(CR303000.AccountSummary.BusinessAccount, baID)
Dim updateBACommands As Command() = {baKeyVal, CR303000.Actions.ConverToCustomer}
Dim updateBaResult As CR303000Content() = m_context.CR303000Submit(updateBACommands)
' just like with Lead, the Customer record now needs to be saved
' add other fields required for Customer
Dim customerNameVal As Value = CreateValue(AR303000.CustomerSummary.CustomerName, CreateCustomerFullName(firstName, LastName))
Dim classVal As Value = CreateValue(AR303000.GeneralInfoFinancialSettings.CustomerClass, "DEFAULT")
Dim statementCycleVal As Value = CreateValue(AR303000.GeneralInfoFinancialSettings.StatementCycleID, "ENDOFMONTH")
Dim statementTypeVal As Value = CreateValue(AR303000.BillingSettingsPrintAndEmailSettings.StatementType, "Open Item")
Dim cashDiscountAccountVal As Value = CreateValue(AR303000.GLAccountsCashDiscountAccount.CashDiscountAccount, "10103")
Dim creditVerificationVal As Value = CreateValue(AR303000.GeneralInfoCreditVerificationRulesCreditVerification.CreditVerification, "Disabled")
Dim commandsCustomer As Command() =
{
customerNameVal, classVal, statementCycleVal, statementTypeVal, cashDiscountAccountVal, creditVerificationVal,
AR303000.Actions.Save,
AR303000.CustomerSummary.CustomerID
}
Dim newCustomerContent As AR303000Content() = m_context.AR303000Submit(commandsCustomer)
Dim newCustomerID As String = ""
If newCustomerContent.Length > 0 Then
' this should be exact same as the newBAID, this is just for debugging
newCustomerID = newCustomerContent(0).CustomerSummary.CustomerID.Value
End If
Return newCustomerID
End Function
The result though is that when CR303000Submit is called with the ConverToCustomer action, I get the following error referring to the Default Location Value:
[SoapException: System.Web.Services.Protocols.SoapException: Server was unable to process request.
---> PX.Data.PXFieldValueProcessingException: Error: An error occurred while processing the field Default Location value 15497 Error: Default Location '15497' cannot be found in the system.. ---> PX.Data.PXSetPropertyException: Error: DefLocationID '15497' cannot be found in the system.
at PX.Data.PXSelectorAttribute.throwNoItem(String[] restricted, Boolean external, Object value)
at PX.Data.PXSelectorAttribute.FieldVerifying(PXCache sender, PXFieldVerifyingEventArgs e)
at PX.Data.PXCache.OnFieldVerifying(String name, Object row, Object& newValue, Boolean externalCall)
at PX.Data.PXCache`1.a(TNode& A_0)
--- End of inner exception stack trace ---
at PX.Data.PXCache`1.Insert(Object data, Boolean bypassinterceptor)
at PX.Data.PXCache`1.Insert(Object data, Boolean bypassinterceptor)
at PX.Data.PXCache`1.Insert(Object data)
at PX.Data.PXCache`1.Extend[Parent](Parent item)
at PX.Objects.CR.BusinessAccountMaint.ConverToCustomer(PXAdapter adapter)
at PX.Data.PXAction`1.a(PXAdapter A_0)
at PX.Data.PXAction`1.<Press>d__c.MoveNext()
at PX.Data.PXAction`1.<Press>d__c.MoveNext()
at PX.Api.SyImportProcessor.SyStep.CommitChanges(Object itemToBypass, PXFilterRow[] targetConditions, PXFilterRow[] filtersForAction)
at PX.Api.SyImportProcessor.ExportTableHelper.ExportTable()
at PX.Api.ScreenUtils.Submit(String screenId, Command[] commands, SchemaMode schemaMode, PXGraph& graph, String& redirectContainerView, String& redirectScreen, Boolean mobile, Dictionary`2 viewFilters)
at PX.Api.Services.ScreenService.Submit(String id, IEnumerable`1 commands, SchemaMode schemaMode, Boolean mobile, PXGraph& forceGraph, String& redirectContainerView, String& redirectScreen, Dictionary`2 viewFilters)
at PX.Api.Services.ScreenService.Submit(String id, IEnumerable`1 commands, SchemaMode schemaMode)
at PX.Api.Soap.Screen.ScreenGate.Submit(Command[] commands)
--- End of inner exception stack trace ---]
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +35
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1724
Source Error
Line 1555: <System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://www.acumatica.com/generic/CR303000/Submit", RequestNamespace:="http://www.acumatica.com/generic/", ResponseNamespace:="http://www.acumatica.com/generic/", Use:=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle:=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)> _
Line 1556: Public Function CR303000Submit(ByVal commands() As Command) As <System.Xml.Serialization.XmlArrayAttribute("SubmitResult"), System.Xml.Serialization.XmlArrayItemAttribute("Content")> CR303000Content()
Line 1557: Dim results() As Object = Me.Invoke("CR303000Submit", New Object() {commands})
Line 1558: Return CType(results(0),CR303000Content())
Line 1559: End Function
The other thing I tried was to change the commands for the CR303000Submit to add a Save action:
Dim updateBACommands As Command() = {baKeyVal, CR303000.Actions.ConverToCustomer, CR303000.Actions.Save}
That gets me past that line without an error, but then when I call the AR303000Submit it just creates a separate Customer record with a different Customer/Business Account ID rather than converting the existing Business Account.

There are two problems here:
An error occurred while processing the field Default Location value 15497 Error: Default Location '15497' cannot be found in the system.
I think this is your data problem. Login with browser and check this Business Account manually. I think you will receive same error.
Convert To Customer action problem
This action produce redirect. It is a problem. But there is a solution:
Create new customization Project
Create GraphExtension for Grapth "BusinessAccountMaint"
Insert next code
using System;
using System.Collections;
using Avalara.AvaTax.Adapter.AvaCert2Service;
using PX.Common;
using PX.Data;
using PX.Data.EP;
using PX.Objects.AP;
using PX.Objects.CS;
using PX.Objects.CT;
using PX.Objects.SO;
using PX.SM;
using System.Collections.Generic;
using PX.Objects;
using PX.Objects.CR;
namespace PX.Objects.CR
{
public class BusinessAccountMaint_Extension : PXGraphExtension
{
public PXAction<BAccount> convertToCustomerAndSave;
// hidden action. Used in API calls
[PXUIField(DisplayName = "Convert To Customer And Save", Visible = false, MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.Process)]
public virtual IEnumerable ConvertToCustomerAndSave(PXAdapter adapter)
{
try
{
return Base.ConverToCustomer(adapter);
}
catch (PXRedirectRequiredException e) // catch redirect exception
{
(e.Graph as AR.CustomerMaint).Save.Press(); // Save our new customer
return adapter.Get();
}
}
}
}
Save and Publish
Regenerate Service Reference (WSDL)
Use new action in your cade
static void Main(string[] args)
{
var client = new ScreenSoapClient();
client.Login("admin", "123");
var baSchema = client.CR303000GetSchema();
var commands = new Command[]
{
new Value
{
Value = "MAURICES",
LinkedCommand = baSchema.AccountSummary.BusinessAccount
},
baSchema.Actions.ConvertToCustomerAndSave // use our new action instead of default
};
client.CR303000Submit(commands);
}
This code will convert Business Account to Customer and Save it immediately

Related

Executing an Insert on a Custom Graph Causing Error

I am trying to insert a new record into a custom table in the database. This is being performed through a graph extension onto the SO graph. The code is as follows:
public PXAction<PX.Objects.SO.SOOrder> addToDatabase;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Send to Manufacturing")]
protected void AddToDatabase()
{
try
{
Flow2 graphWO = PXGraph.CreateInstance<Flow2>();
EMPWorkOrder wo = null;
foreach (PXResult<SOLine, InventoryItem> line in PXSelectJoin<SOLine, LeftJoinSingleTable<InventoryItem, On<InventoryItem.inventoryID, Equal<SOLine.inventoryID>>>,
Where<SOLine.orderNbr, Equal<Current<SOOrder.orderNbr>>>>.Select(Base, Base.Document.Current.OrderNbr))
{
PXCache sender = Base.Transactions.Cache;
SOLine soLine = (SOLine)line;
InventoryItem item = (InventoryItem)line;
SOLineExt lineExt = sender.GetExtension<SOLineExt>(soLine);
if (lineExt.UsrisSentToManufacturing != true)
{
wo = new EMPWorkOrder();
wo.Soid = Base.Document.Current.OrderNbr;
wo.ItemCD = item.InventoryCD;
wo.LineNbr = soLine.LineNbr;
wo.QtyReceived = 0;
wo.DateReceived = null;
wo.QtyComplete = 0;
wo.QtySentToInventory = 0;
wo.RouteId = "0";
wo.KitId = -1;
wo.IsStarted = false;
wo.NoteID = Guid.NewGuid();
graphWO.Document.Insert(wo);
graphWO.Actions.PressSave();
graphWO.Clear();
}
}
throw new PXException("Successfully moved to Manufacturing");
}
}
When executing the code, the error I receive is the following:
Error#14: Inserting 'EMPWorkOrder' record raised one or more errors. Please review.
When I go into the trace, this is the information it gives me:
12/16/2016 1:44:23 PM Error:
Error #14: Inserting 'EMPWorkOrder' record raised one or more errors. Please review.
at PX.Objects.SO.SOOrderEntry_Extension.AddToDatabase()
at PX.Data.PXAction`1.<>c__DisplayClass3_0.<.ctor>b__0(PXAdapter adapter)
at PX.Data.PXAction`1.a(PXAdapter A_0)
at PX.Data.PXAction`1.d__31.MoveNext()
at PX.Data.PXAction`1.d__31.MoveNext()
at PX.Web.UI.PXBaseDataSource.tryExecutePendingCommand(String viewName, >String[] sortcolumns, Boolean[] descendings, Object[] searches, Object[] >parameters, PXFilterRow[] filters, DataSourceSelectArguments arguments, >Boolean& closeWindowRequired, Int32& adapterStartRow, Int32& adapterTotalRows)
at PX.Web.UI.PXBaseDataSource.ExecuteSelect(String viewName, DataSourceSelectArguments arguments, PXDSSelectArguments pxarguments)
Is there any reason that my record wouldn't be inserting into the custom table I made? If you need any other information to develop a resolution to this issue, please feel free to ask.
Eric, you most likely get this error because of some empty field or fields (with no value or null value assigned) decorated with the PXDefaultAttribute. While running the code under debugger, you should get access to a more detailed exception through the InnerException property of the originally thrown exception.
On a side note, let me also advise you to add SOLine.orderType field in Where clause of your BQL query in the beginning of action delegate, as there are 2 key fields defined for the SOOrder DAC has: OrderType and OrderNbr

Debugging error: One of more field types not installed properly

I attempting to add a folder to a custom Document Set with in a Document library. However something is not right one or more of the fields and the following error message is not providing me info that would narrow it down. I am looking for a way to identify and fix the offending fields in library.
Microsoft.SharePoint.Client.ServerException was unhandled
HResult=-2146233088
Message=One or more field types are not installed properly. Go to the list settings page to delete these fields.
ServerErrorCode=-2130575340
ServerErrorTraceCorrelationId=0e7a749d-70a8-2000-36cf-14f8618874a2
ServerErrorTypeName=Microsoft.SharePoint.SPException
ServerStackTrace=""
Source=Microsoft.SharePoint.Client.Runtime
StackTrace:
at Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream(Stream responseStream)
at Microsoft.SharePoint.Client.ClientRequest.ProcessResponse()
at Microsoft.SharePoint.Client.ClientRequest.ExecuteQueryToServer(ChunkStringBuilder sb)
at Microsoft.SharePoint.Client.ClientRequest.ExecuteQuery()
at Microsoft.SharePoint.Client.ClientRuntimeContext.ExecuteQuery()
at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery()
at Microsoft.SharePoint.Client.ClientContextExtensions.ExecuteQueryImplementation(ClientRuntimeContext clientContext, Int32 retryCount, Int32 delay)
at Microsoft.SharePoint.Client.FileFolderExtensions.CreateFolderImplementation(FolderCollection folderCollection, String folderName, Folder parentFolder)
at Microsoft.SharePoint.Client.FileFolderExtensions.CreateFolder(Folder parentFolder, String folderName)
at AddFolderToDocSet.Program.Main(String[] args) in C:\Users\user\Documents\Visual Studio 2015\Projects\PnPCoreTest\AddFolderToDocSet\Program.cs:line 51
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
This is the code I am using to add the folder which leverages the PNP-Sites-Core library.
// Get Root Folders collection for
var projLibRootFldrs = prjLib.RootFolder;
ctx.Load(projLibRootFldrs, pf => pf.Folders);
ctx.ExecuteQueryRetry();
// Get the Document Set
Folder f = projLibRootFldrs.EnsureFolder("Test1");
f.CreateFolder("foo"); // Error here
Update: 4/21/2016
After painstaking analysis (errr... trial, error, repeat for ever) I have narrowed this down to the fields in the "Shared Columns" section of the "Document Set Settings" It seems when I check any of those the error occurs. When I uncheck all the fields so none are shared I am able to add the folder.
Update: 4/26/2016
Here are the exact steps needed to recreate this error.
Here is the exact console program used to create the folder:
static void Main(string[] args)
{
string pwd = System.Environment.GetEnvironmentVariable("SOME_PWD", EnvironmentVariableTarget.User);
if (string.IsNullOrEmpty(pwd))
{
System.Console.Write("MSOPWD user environment variable empty, cannot continue. Press any key to end.");
System.Console.ReadKey();
return;
}
// Get access to source site
using (var ctx = new ClientContext("https://mysite.sharepoint.com/sites/demo3"))
{
//Provide count and pwd for connecting to the source
var passWord = new SecureString();
foreach (char c in pwd.ToCharArray()) passWord.AppendChar(c);
ctx.Credentials = new SharePointOnlineCredentials("me#email.com", passWord);
Web web = ctx.Web;
string docSetLibName = "P1";
string docSetFolderName = "Test1";
string folderName = "Foo1";
try
{
List list = EnsureTargetTestFolder(ctx, docSetLibName);
Folder docSet = EnsureTestDocumentSet(ctx, list, docSetFolderName);
MakeStandardFolder(ctx, docSet, folderName);
}catch(Exception exp)
{
Console.ForegroundColor = ConsoleColor.White;
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine("ERROR:" + Environment.NewLine);
Console.WriteLine(exp.Message + Environment.NewLine);
Console.WriteLine(Environment.NewLine);
Console.ResetColor();
}
Console.WriteLine("Done...");
}
Console.ReadKey();
}
private static List EnsureTargetTestFolder(ClientContext ctx, string docSetLibName)
{
if (ctx.Web.ListExists(docSetLibName) == false) {
Console.WriteLine(String.Format("List {0} not found... creating new!", docSetLibName));
// Make the list
List newList = ctx.Web.CreateList(ListTemplateType.DocumentLibrary, docSetLibName, false, true, "", true);
newList.AddContentTypeToListByName("DocSetTest");
newList.RemoveContentTypeByName("Document");
newList.EnableFolderCreation = true;
return newList;
}else
{
Console.WriteLine(String.Format("List {0} exists!", docSetLibName));
return ctx.Web.GetListByTitle(docSetLibName);
}
}
private static Folder EnsureTestDocumentSet(ClientContext ctx, List list, string docSetLibName)
{
if (list.RootFolder.FolderExists(docSetLibName) == false)
{
Console.WriteLine(String.Format("Document Set '{0}'does not exist... creating new!", docSetLibName));
Folder fldr = list.RootFolder.CreateDocumentSet(docSetLibName, ctx.Web.GetContentTypeByName("DocSetTest").Id);
return fldr;
}else
{
Console.WriteLine(String.Format("Document Set '{0}\\{1}' exists", list.EntityTypeName, docSetLibName));
return list.RootFolder.ResolveSubFolder(docSetLibName);
}
}
private static void MakeStandardFolder(ClientContext ctx, Folder docSet, string folderName)
{
if (docSet.FolderExists(folderName) == false)
{
Console.WriteLine(String.Format("Folder {0} does not exist ... creating new!", folderName));
docSet.CreateFolder(folderName);
}else
{
Console.WriteLine(String.Format("Folder {0} already exists", folderName));
}
}
I have tested the steps you provided . Yes , with your steps the error occured .
I notice the "DocSetTest ID" column may cause the error :
1.create "DocumentSetName ID" column and make it shared , the error occured .
2.create "ID" column and make it shared , the error occured .
3.create "DocumentSetName_ID" column and make it shared , it works fine .
4.create "IDDocumentSetName" column and make it shared , it works fine .
So maybe your "ID" or "DocumentSetName ID" column may conflict something (perhaps existed "ID" column) when using OfficeDevPnP.Core library. Try to change the name of the columns and check the results .
The trick to making this work was to first access and remove the fields in the SharedFields collection of the DocumentSetTemplate, then make the folder, then restore the SharedFields. Here are the methods used to do this.
private static void HideSharedFields(ClientContext ctx, ContentType ct, out SharedFieldCollection unsharedFields)
{
DocumentSetTemplate docSetTemplate = DocumentSetTemplate.GetDocumentSetTemplate(ctx, ct);
SharedFieldCollection sharedFields = docSetTemplate.SharedFields;
unsharedFields = sharedFields;
ctx.Load(sharedFields);
ctx.ExecuteQueryRetry();
foreach(var fld in sharedFields)
{
Console.WriteLine(String.Format(" - Removing SharedField '{0}'", fld.Title));
docSetTemplate.SharedFields.Remove(fld);
fld.UpdateAndPushChanges(true);
}
docSetTemplate.Update(true);
ctx.ExecuteQueryRetry();
}
private static void RevealSharedFields(ClientContext ctx, ContentType ct, SharedFieldCollection unsharedFields)
{
DocumentSetTemplate docSetTemplate = DocumentSetTemplate.GetDocumentSetTemplate(ctx, ct);
foreach (var fld in unsharedFields)
{
Console.WriteLine(String.Format(" + Adding SharedField '{0}'", fld.Title));
docSetTemplate.SharedFields.Add(fld);
fld.UpdateAndPushChanges(true);
}
docSetTemplate.Update(true);
ctx.ExecuteQueryRetry();
}

Exception thrown when using Glimpse and Postal

I'm just starting to use Glimpse with my MVC5 project and have run into an issue when I use Postal to send an email without disabling Glimpse. I've been able to narrow it down to an issue with both packages - it doesn't occur if the Glimpse cookie has not been turned on.
In Fiddler, I checked the difference between the two. When it threw the exception, the cookie was
glimpsePolicy=On
when it worked (Glimpse was off) there were two cookies
glimpseId=FBar; glimpsePolicy=
The exception I get is
System.ArgumentNullException: Value cannot be null.
Parameter name: controllerContext
at System.Web.Mvc.ChildActionValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
at Castle.Proxies.Invocations.ValueProviderFactory_GetValueProvider.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Glimpse.Core.Extensibility.ExecutionTimer.Time(Action action)
at Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.ValueProviderFactoryProxy.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ControllerBase.get_ValueProvider()
at Glimpse.Mvc.Message.ActionMessageExtension.AsActionMessage[T](T message, ControllerBase controller)
at Glimpse.Mvc.AlternateType.ViewEngine.FindViews.PostImplementation(IAlternateMethodContext context, TimerResult timerResult)
at Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.IViewEngineProxy.FindView(ControllerContext controllerContext, String viewName, String masterName, Boolean useCache)
at System.Web.Mvc.ViewEngineCollection.<>c__DisplayClass6.<FindView>b__4(IViewEngine e)
at System.Web.Mvc.ViewEngineCollection.Find(Func`2 lookup, Boolean trackSearchedPaths)
at System.Web.Mvc.ViewEngineCollection.Find(Func`2 cacheLocator, Func`2 locator)
at Postal.EmailViewRenderer.Render(Email email, String viewName)
at Postal.EmailService.Send(Email email)
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0)
at System.Web.Mvc.ActionMethodDispatcher.<>c__DisplayClass1.<WrapVoidAction>b__0(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__36(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
at Castle.Proxies.Invocations.AsyncControllerActionInvoker_EndInvokeActionMethod.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Glimpse.Mvc.AlternateType.AsyncActionInvoker.EndInvokeActionMethod.NewImplementation(IAlternateMethodContext context)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.AsyncControllerActionInvokerProxy.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3c()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass45.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3e()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass30.<BeginInvokeActionMethodWithFilters>b__2f(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<>c__DisplayClass28.<BeginInvokeAction>b__19()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<BeginInvokeAction>b__1b(IAsyncResult asyncResult)
I created a quick action to test it. The controller code is:
public void TestEmailExt()
{
var confirmationToken = "ConfirmationToken";
var Phone1 = "**********";
dynamic email = new Email("RegEmail");
email.To = "**#gmail.com";
email.UserName = "UserName";
email.ConfirmationToken = confirmationToken;
email.Phone = Extensions.Right(Phone1, 4);
if (email.To.Contains("#mydomain"))
email.From = INTERNAL_EMAIL_FROM;
else
email.From = EXTERNAL_EMAIL_FROM;
email.Send();
}
The reason this fails is because the Postal library creates its own HttpContext instance while rendering the email view as the decompiled CreateControllerContext method inside Postal's EmailViewRenderer class shows:
private ControllerContext CreateControllerContext()
{
HttpContextWrapper httpContextWrapper = new HttpContextWrapper(new HttpContext(new HttpRequest("", this.UrlRoot(), ""), new HttpResponse(TextWriter.Null)));
RouteData routeData = new RouteData();
routeData.Values["controller"] = (object) this.EmailViewDirectoryName;
return new ControllerContext(new RequestContext((HttpContextBase) httpContextWrapper, routeData), (ControllerBase) new EmailViewRenderer.StubController());
}
This means that the setup that Glimpse does at BeginRequest is completely removed, while the hooks are still in place to intercept MVC related calls.
We've had a similar issue where I gave a similar response to why this is not working.
UPDATE :
I mentioned above that a similar issue had been reported previously, but while I was trying to find a more appropriate solution, it seemed that this case is slightly different in that respect that the other similar issue actually executes a controller with the freshly created context resulting in a NullReferenceException in Glimpse specific code, while here we get a NullReferenceException inside MVC specific code, albeit triggered by Glimpse.
System.ArgumentNullException: Value cannot be null.
Parameter name: controllerContext
at System.Web.Mvc.ChildActionValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
And the exception we get here is because the ControllerContext property on the StubController instance (created inline) is null, which would normally be set when executing the controller (which is not the case here).
So the workaround that I proposed below still applies, but can be avoided if the code of the CreateControllerContext() above is slightly modified:
private ControllerContext CreateControllerContext()
{
HttpContextWrapper httpContextWrapper = new HttpContextWrapper(new HttpContext(new HttpRequest("", this.UrlRoot(), ""), new HttpResponse(TextWriter.Null)));
RouteData routeData = new RouteData();
routeData.Values["controller"] = (object) this.EmailViewDirectoryName;
// MODIFIED
var stubController = new EmailViewRenderer.StubController();
var controllerContext = new ControllerContext(new RequestContext(httpContextWrapper, routeData), stubController);
stubController.ControllerContext = controllerContext;
return controllerContext;
}
I've created an issue for this on the Postal issue tracker
END OF UPDATE
I think the best solution, for now, is to disable Glimpse while calling into Postal and restore normal Glimpse behavior back again afterwards. We might include this one way or the other into the Glimpse Core library in one of the upcoming releases as it seems that disabling Glimpse during a specific part of the request processing logic doesn't seem to be that uncommon, but for now the following snippet might help you (beware it makes use of a Glimpse internal key which is not guaranteed to be there in an upcoming release)
public class GlimpseSuppressionScope : IDisposable
{
private const string GlimpseRequestRuntimePermissionsKey = "__GlimpseRequestRuntimePermissions";
private readonly HttpContext currentHttpContext;
private readonly RuntimePolicy? currentRuntimePolicy;
private bool disposed;
public GlimpseSuppressionScope(HttpContext currentHttpContext)
{
if (currentHttpContext == null)
{
throw new ArgumentNullException("currentHttpContext");
}
this.currentHttpContext = currentHttpContext;
this.currentRuntimePolicy = this.currentHttpContext.Items[GlimpseRequestRuntimePermissionsKey] as RuntimePolicy?;
this.currentHttpContext.Items[GlimpseRequestRuntimePermissionsKey] = RuntimePolicy.Off;
}
~GlimpseSuppressionScope()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
if (this.currentHttpContext != null)
{
this.currentHttpContext.Items.Remove(GlimpseRequestRuntimePermissionsKey);
if (this.currentRuntimePolicy.HasValue)
{
this.currentHttpContext.Items[GlimpseRequestRuntimePermissionsKey] = this.currentRuntimePolicy.Value;
}
}
}
this.disposed = true;
}
}
}
which you can then use in your controller action method as shown below:
public void TestEmailExt()
{
using (new GlimpseSuppressionScope(System.Web.HttpContext.Current))
{
var confirmationToken = "ConfirmationToken";
var Phone1 = "**********";
dynamic email = new Email("RegEmail");
email.To = "**#gmail.com";
email.UserName = "UserName";
email.ConfirmationToken = confirmationToken;
email.Phone = Extensions.Right(Phone1, 4);
if (email.To.Contains("#mydomain"))
email.From = INTERNAL_EMAIL_FROM;
else
email.From = EXTERNAL_EMAIL_FROM;
email.Send();
}
}

Binding an external (BCS) list to a SPDataGrid in Sharepoint 2010

I've created a BCS service and created an external list from the BCS content-type.
I have then tried to add a SPGridView control to a webpart. I am getting an exception as soon as I call my SPGridview's DataBind() method, here is what the code looks like:
namespace BCSService.CustomWebPart
{
[ToolboxItemAttribute(false)]
public class CustomWebPart : WebPart
{
// Visual Studio might automatically update this path when you change the Visual Web Part project item.
private const string _ascxPath = #"~/_CONTROLTEMPLATES/BCSShims/CustomWorkEstimateWebPart/CustomWorkEstimateWebPartUserControl.ascx";
private SPGridView gv;
private SPDataSource spdata;
private SPSite site;
private SPWeb web;
private SPList we_list;
protected override void CreateChildControls()
{
base.CreateChildControls();
Control control = Page.LoadControl(_ascxPath);
Controls.Add(control);
this.site = SPContext.Current.Site;
this.web = this.site.OpenWeb();
this.we_list = this.web.Lists["BCSList"];
this.spdata = new SPDataSource();
Controls.Add(this.spdata);
this.gv = new SPGridView();
this.gv.AutoGenerateColumns = false;
Controls.Add(this.gv);
}
protected void BindColumns()
{
this.spdata.DataSourceMode = SPDataSourceMode.List;
this.spdata.List = this.we_list;
this.spdata.UseInternalName = true;
this.spdata.DataBind();
this.gv.AllowSorting = false;
this.gv.PageSize = 200;
this.gv.DataSource = this.spdata;
Dictionary<string, string> listFields = new Dictionary<string, string>();
listFields.Add("CompanyName", "Company Name");
listFields.Add("ContactDetails", "Contact Details");
listFields.Add("ProjectDescription", "Description");
foreach (var row in listFields)
{
SPBoundField boundField = new SPBoundField();
boundField.HeaderText = row.Value;
boundField.DataField = row.Key;
this.gv.Columns.Add(boundField);
}
}
protected override void RenderContents(HtmlTextWriter writer)
{
if (!Page.IsPostBack)
{
this.BindColumns();
this.gv.DataBind();
}
this.gv.RenderControl(writer);
}
}
}
The DataBind() method is throwing the following exception:
Object reference not set to an instance of an object.
at Microsoft.SharePoint.WebControls.SPDataSourceViewResultItem.System.ComponentModel.ICustomTypeDescriptor.GetProperties()
at System.ComponentModel.TypeDescriptor.MergedTypeDescriptor.System.ComponentModel.ICustomTypeDescriptor.GetProperties()
at System.ComponentModel.TypeDescriptor.GetPropertiesImpl(Object component, Attribute[] attributes, Boolean noCustomTypeDesc, Boolean noAttributes)
at System.ComponentModel.TypeDescriptor.GetProperties(Object component)
at Microsoft.SharePoint.WebControls.SPBoundField.DataBindingEventHandler(Object sender, EventArgs e)
at System.Web.UI.Control.OnDataBinding(EventArgs e)
at System.Web.UI.Control.DataBind(Boolean raiseOnDataBinding)
at System.Web.UI.Control.DataBindChildren()
at System.Web.UI.Control.DataBind(Boolean raiseOnDataBinding)
at System.Web.UI.Control.DataBindChildren()
at System.Web.UI.Control.DataBind(Boolean raiseOnDataBinding)
at System.Web.UI.WebControls.GridView.CreateRow(Int32 rowIndex, Int32 dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState, Boolean dataBind, Object dataItem, DataControlField[] fields, TableRowCollection rows, PagedDataSource pagedDataSource)
at System.Web.UI.WebControls.GridView.CreateChildControls(IEnumerable dataSource, Boolean dataBinding)
at Microsoft.SharePoint.WebControls.SPGridView.CreateChildControls(IEnumerable dataSource, Boolean dataBinding)
at System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.GridView.PerformDataBinding(IEnumerable data)
at System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data)
at System.Web.UI.WebControls.DataBoundControl.PerformSelect()
at BCSService.CustomWebPart.CustomWorkEstimateWebPart.RenderContents(HtmlTextWriter writer)
I have verified that this.we_list is not empty (In Visual Studio debugger's locals tab, I can see this.we_list.Items.Count is set to 99, although this.we_list.ItemCount is set to 0.)
Also, that all seems to work okay against non-external lists, but I see nothing in the docs about external lists not being supported in SPGridView or SPDataSource, and the exception makes no mention of external lists not being supported. Has anyone run into this issue?
This seems to be a possible Sharepoint Server 2010 bug (I'm using Sharepoint Server 2010 Enterprise Edition). Ultimately, I solved the problem by adding a to_datatable() conversion method to my BCS service entity that simply uses the statis ReadList() method, collects its output, and inserts the data into a DataTable object.

SharePoint 2007 (wss) search and Unable to validate data Exception

We have a problem with SharePoint's search box. Whenever we try to search for something we get:
Unable to validate data. at
System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean
fEncrypt, Byte[] buf, Byte[] modifier,
Int32 start, Int32 length, IVType
ivType, Boolean useValidationSymAlgo)
at
System.Web.UI.ObjectStateFormatter.Deserialize(String
inputString) exeption.
Does any one know the reason for this exception, or a way to work around it?
New entry:
I'm using a SPGridView where i use the datakeys property in a web part. The webpart works, but we found that using the datakeys property breaks seach in that if you try to use the search textbox and click the seach button it gets this exception:
Unable to validate data. at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, IVType ivType, Boolean useValidationSymAlgo)
at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
This is what i have tryed to do:
Make the gridview not spgridview and set autogenerate true (works)
Remove the datakeynames (works)
Test with a empty gridvew (failes)
Test with a non-empty gridview (failes)
Change Machine Keys (failes)
Turn of view state on the gridvew (failes)
Move the gridview ti a ascx file (failes)
I can't seem to figure this one out. Have enyone got this error and been able to work around it?
EDit 10.09.2009
This is the last code I tested. I used a MSDN excample as referance. I have also tried without Data table MSDN Example
public class TestErrorGridView : System.Web.UI.WebControls.WebParts.WebPart
{
Control ascxToAdd;
protected DataTable PropertyCollection = new DataTable();
private DataColumn key;
public TestErrorGridView()
{
key = PropertyCollection.Columns.Add("ID", typeof(string));
PropertyCollection.Columns.Add("Name", typeof(string));
}
public void AddProperty(TestBindObject data)
{
DataRow newRow = PropertyCollection.Rows.Add();
newRow["ID "] = data.ID;
newRow["Name"] = data.Name;
}
public void BindGrid(SPGridView grid)
{
SPBoundField fldPropertyName = new SPBoundField();
fldPropertyName.HeaderText = "ID";
fldPropertyName.DataField = "ID";
grid.Columns.Add(fldPropertyName);
SPBoundField fldPropertyValue = new SPBoundField();
fldPropertyValue.HeaderText = "Name";
fldPropertyValue.DataField = "Name";
grid.Columns.Add(fldPropertyValue);
PropertyCollection.PrimaryKey = new DataColumn[] { key };
grid.DataSource = PropertyCollection.DefaultView;
grid.DataKeyNames = new string[] { key.ColumnName };
grid.DataBind();
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
protected override void CreateChildControls()
{
base.CreateChildControls();
TestBindObject t1 = new TestBindObject() { ID = 1, Name = "Test3" };
this.AddProperty(t1);
SPGridView testGrid = new SPGridView() { AutoGenerateColumns = false };
this.BindGrid(testGrid);
this.Controls.Add(testGrid);
}
}
[Serializable]
public class TestBindObject
{
public int ID { get; set; }
public string Name { get; set; }
}
From the error message I'd say that you are operating in a web-farm environment. Have you set the same machineKey in each of the SharePoint web.config files? See this link for a little more info.

Resources