Essentially what the title says, for whatever reason when I call clientContext.ExecuteQuery(); and for example the list the data is going into has a missing column, I don't get an exception, it actually just runs as expected and I have to go and investigate what might have caused the data to not appear.
The NuGet package i'm using is Microsoft.SharePoint2016.CSOM version 16.0.4690.1000
Any hints, or suggestions to point me in the right direction appreciated. It's entirely possible I'm being a bit dim here.
Here's the full code block I'm using for updating list items:
public override object UpdateEntity(object entity)
{
if (entity == null)
{
// if the definition is null throw argument null exception.
throw new ArgumentNullException(nameof(SharePointDefinition));
}
// check for incorrect type being passed in that we can still handle
if (entity is List<SharePointDefinition> definitions)
{
return UpdateEntities(definitions);
}
ExceptionHandlingScope exceptionScopeFetch = new ExceptionHandlingScope(clientContext);
ExceptionHandlingScope exceptionScopeSubmit = new ExceptionHandlingScope(clientContext);
// run single definition submit to SP.
if (entity is SharePointDefinition definition)
{
// variables.
IntegrationEventLog log = new IntegrationEventLog();
EventInformation ei = new EventInformation();
List list = null;
ListItemCollection listItemCol = null;
using (exceptionScopeFetch.StartScope())
{
using (exceptionScopeFetch.StartTry())
{
// get the required list
list = clientContext.Web.Lists.GetByTitle(definition.ListName);
// create query
listItemCol = list.GetItems(CamlQuery.CreateAllItemsQuery());
// set these items for retrieval.
clientContext.Load(listItemCol);
}
using (exceptionScopeFetch.StartCatch())
{
// Assume that if there's an exception, it can only be
// because there is no list with the specified title, so report this back.
if (exceptionScopeFetch.HasException)
{
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = $"Hit SharePoint exception handler during list and data pull: Message: {exceptionScopeFetch.ErrorMessage}",
StackTrace = exceptionScopeFetch.ServerStackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
}
}
using (exceptionScopeFetch.StartFinally())
{
//
}
}
// get item instances first
try
{
clientContext.ExecuteQuery();
}
catch (Exception genEx)
{
// return failure log.
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = "Errored trying to get data from SharePoint list ready for update operation; see stacktrace for more information.",
StackTrace = genEx.StackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
return false;
}
// this is the column we want to overwrite.
var comparisonColumn = definition.UpdateIdentifier ?? "";
//List col to dict
var listItems = listItemCol.Cast<ListItem>().ToList();
// Now we know if we were able to retrieve existing data, perform submit.
using (exceptionScopeSubmit.StartScope())
{
using (exceptionScopeSubmit.StartTry())
{
// loop through our rows
foreach (var row in definition.RowData)
{
int existingItemIndex = -1;
// see if the row exists already
if (!string.IsNullOrEmpty(comparisonColumn) && listItems.Count != 0)
{
existingItemIndex = listItems.FindIndex(x => x[comparisonColumn].ToString() == row[comparisonColumn]);
}
if (existingItemIndex != -1 && listItems.Count != 0)
{
// item exists - loop through our row columns
foreach (var keyValuePair in row)
{
// they key relates to a column, the Value to the rows colum Value.
listItems[existingItemIndex].ParseAndSetFieldValue(keyValuePair.Key, keyValuePair.Value);
}
// update this item
listItems[existingItemIndex].Update();
}
else
{
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
ListItem newItem = list.AddItem(itemCreateInfo);
// loop through our row columns
foreach (var keyValuePair in row)
{
// they key relates to a column, the Value to the rows colum Value.
newItem[keyValuePair.Key] = keyValuePair.Value;
}
newItem.Update();
}
}
}
using (exceptionScopeSubmit.StartCatch())
{
// Assume that if there's an exception, it can only be
// because there is no list with the specified title, so report this back.
if (exceptionScopeFetch.HasException)
{
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = $"Error at SharePoint exception handler during submit to list: Message: {exceptionScopeFetch.ErrorMessage}",
StackTrace = exceptionScopeFetch.ServerStackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
}
}
using (exceptionScopeSubmit.StartFinally())
{
//
}
}
// try to execute submit.
try
{
clientContext.ExecuteQuery();
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentSuccess,
LoggingSeverity = LoggingSeverity.Information,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = "No exceptions were thrown from the Execution process.",
StackTrace = "",
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Information;
log.EventID = LoggingSeverity.Information;
log.Message = JsonConvert.SerializeObject(ei);
}
catch (Exception genEx)
{
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = $"Data failed to be updated within SharePoint - {genEx.Message} - see stacktrace for more information.",
StackTrace = genEx.StackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
return false;
}
AddToLog(log);
return true;
}
else
{
// If a different definition type is passed in throw an appropriate exception.
// This should be caught at runtime only.
throw new TypeLoadException(nameof(SharePointDefinition));
}
}
I checked the code you posted and I see that you are updating the list of objects, in your case listItems, instead of a ListItem in ListItemCollection, in your case listItemCol.
To be more clear, I believe you can try to replace listItems with listItemCol.
For instance, instead of:
listItems[existingItemIndex].ParseAndSetFieldValue(keyValuePair.Key, keyValuePair.Value);
use
listItemCol[existingItemIndex][keyValuePair.Key] = keyValuePair.Value;
So I went away and re-read a lot of documentation and looked over some examples, and I wondered why the exception handler never returned errors even though it's obvious there were issues with the query being executed. If you look at the Microsoft documentation and their example here you'll see that they don't show you how to use exceptionScopeSubmit.HasException component of the exception scope object. Which lead to a really stupid assumption on my part. It turns out that the exception block runs on the SharePoint server and should be used to fix issues you might have caused during an expected exception in your query.
Not only that but wrapping the ExecuteQuery in the try catch is redundant when using an exception scope as it means that method will no longer throw an exception. You actually have to assess exceptionScopeSubmit.HasException after the execution to pull back some more detailing information on errors reported by the SharePoint server side execution of your query.
So now I'm using it as below, and I can get detailed error information without having to do some stupid manual debugging which would easily take me hours to track down silly issues. So in case anyone stumbles across this having the same issues, I hope it helps.
ExceptionHandlingScope exceptionScopeFetch = new ExceptionHandlingScope(clientContext);
// variables.
IntegrationEventLog log = new IntegrationEventLog();
EventInformation ei = new EventInformation();
List list = null;
ListItemCollection listItemCol = null;
using (exceptionScopeFetch.StartScope())
{
using (exceptionScopeFetch.StartTry())
{
// get the required list
list = clientContext.Web.Lists.GetByTitle(definition.ListName);
// create query
listItemCol = list.GetItems(CamlQuery.CreateAllItemsQuery());
// set these items for retrieval.
clientContext.Load(listItemCol);
}
using (exceptionScopeFetch.StartCatch())
{
//
}
using (exceptionScopeFetch.StartFinally())
{
//
}
}
// get item instances first
clientContext.ExecuteQuery();
if (exceptionScopeSubmit.HasException)
{
ei = new EventInformation()
{
LoggingEventType = LoggingEventType.DataSentFailure,
LoggingSeverity = LoggingSeverity.HighSeverity,
SerialisedMessage = JsonConvert.SerializeObject(definition),
ServiceMessage = $"Error at SharePoint exception handler during submit to list: Message: {exceptionScopeFetch.ErrorMessage}",
StackTrace = exceptionScopeFetch.ServerStackTrace,
TimeGenerated = DateTime.Now,
TimeWritten = DateTime.Now,
};
log.EventLogEntryType = EventLogEntryType.Error;
log.EventID = LoggingSeverity.HighSeverity;
log.Message = JsonConvert.SerializeObject(ei);
AddToLog(log);
}
Trying to add new customer to NetSuite like it described in sample in manual.
private static void Main(string[] args)
{
ApplicationInfo _appInfo;
var service = new NetSuiteService();
service.CookieContainer = new CookieContainer();
_appInfo = new ApplicationInfo();
_appInfo.applicationId = "FB31C4F2-CA6C-4E5F-6B43-57632594F96";
service.applicationInfo = _appInfo;
var passport = new Passport();
passport.account = "5920356_SB9";
passport.email = "a#a.com";
var role = new RecordRef();
role.internalId = "3";
passport.role = role;
passport.password = "#sdkkr_5543";
try
{
var status = service.login(passport).status;
}
catch (Exception e)
{
Console.Out.WriteLine(e.Message);
throw;
}
var cust = new Customer();
cust.entityId = "XYZ Inc";
cust.altEmail = "aaa#aaa.aaa";
var response = service.add(cust);
Console.Out.WriteLine("response.status.isSuccess " + response.status.isSuccess) ;
Console.Out.WriteLine("response.status.isSuccessSpecified " + response.status.isSuccessSpecified);
service.logout();
}
As result I got:
response.status.isSuccess False
response.status.isSuccessSpecified True
I suppose customer was not inserted. What is wrong and how to know that?
When you call add() on the service, the response contains a status property which contains a statusDetail property. statusDetail is an array of the messages (warnings and errors) that resulted from your add(). You can loop through these to find out why saving your customer record was unsuccessful:
var response = service.add(cust);
if (!response.status.isSuccess)
{
foreach (var error in response.status.statusDetail)
{
Console.WriteLine($"Error creating customer: {error.type} {error.message}");
}
}
I am trying to implement a code to modify entities through WCF Dataservices from the OData client I have generated. I have followed the same principle that was implemented in this link - https://msdn.microsoft.com/en-us/library/dd756368(v=vs.110).aspx
I am getting "CSRF token validation failed" error during the SaveChanges method call. Please see code below:
// Define the URI of the public Northwind OData service.
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
Uri cuanUri =
new Uri("https://xxxx.xxxx.com:44300/sap/opu/odata/sap/CUAN_IMPORT_SRV/",
UriKind.Absolute);
// Create a new instance of the typed DataServiceContext.
DateTime stimestamp = new DateTime();
DateTime dob = new DateTime(1992,05,02);
CUAN_IMPORT_SRV_Entities context = new CUAN_IMPORT_SRV_Entities(cuanUri);
context.SendingRequest2 += SendBaseAuthCredsOnTheRequest;
Contact newContact = Contact.CreateContact("C160717055735", "SAP_ODATA_IMPORT", stimestamp);
//Product newProduct = Product.CreateProduct(0, "White Tea - loose", false);
newContact.CompanyId = "BLUEFIN1";
newContact.CompanyIdOrigin = "SAP_ODATA_IMPORT";
newContact.CountryDescription = "Singapore";
newContact.DateOfBirth = dob;
newContact.EMailAddress = "j_prado#yahoo.com";
newContact.EMailOptIn = "Y";
newContact.FirstName = "Jeffrey1";
newContact.FunctionDescription = "Consultant";
newContact.GenderDescription = "Male";
newContact.LastName = "Prado1";
newContact.PhoneNumber = "+6596492714";
newContact.PhoneOptin = "Y";
Company newCompany = Company.CreateCompany("BLUEFIN1", "SAP_ODATA_IMPORT", stimestamp);
newCompany.IndustryDescription = "1007";
newCompany.CompanyName = "BLUEFIN1";
Interaction newInteraction = Interaction.CreateInteraction("");
newInteraction.CommunicationMedium = "WEB";
newInteraction.ContactId = "C160717055735";
newInteraction.ContactIdOrigin = "SAP_ODATA_IMPORT";
newInteraction.InteractionType = "WEBSITE_REGISTRATION";
newInteraction.Timestamp = stimestamp;
ImportHeader newHeader = ImportHeader.CreateImportHeader("");
newHeader.Timestamp = stimestamp;
newHeader.UserName = "ENG";
newHeader.SourceSystemType = "EXT";
newHeader.SourceSystemId = "HYBRIS";
try
{
// Add the new entities to the CUAN entity sets.
context.AddToImportHeaders(newHeader);
context.AddToContacts(newContact);
context.AddToCompanies(newCompany);
context.AddToInteractions(newInteraction);
// Send the insert to the data service.
DataServiceResponse response = context.SaveChanges();
// Enumerate the returned responses.
foreach (ChangeOperationResponse change in response)
{
// Get the descriptor for the entity.
EntityDescriptor descriptor = change.Descriptor as EntityDescriptor;
if (descriptor != null)
{
Contact addedContact = descriptor.Entity as Contact;
if (addedContact != null)
{
Console.WriteLine("New contact added with ID {0}.",
addedContact.CompanyId);
}
}
}
}
catch (DataServiceRequestException ex)
{
throw new ApplicationException(
"An error occurred when saving changes.", ex);
}
}
private static void SendBaseAuthCredsOnTheRequest(object sender,
SendingRequest2EventArgs e)
{
var authHeaderValue = Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}"
, "XXXXX", "XXXXX")));
e.RequestMessage.SetHeader("Authorization", "Basic " + authHeaderValue); //this is where you pass the creds.
}
The code above fails when invoking: DataServiceResponse response = context.SaveChanges();
I am using a service reference which connects to internet and I want to show message in a message box if ever the connection fails. How will I call message box in the member function of the class which has void return type? This is the member function of the class:
public void ReverseGeocodePoint()
{
try{
string results = "";
string key = "abc";
ReverseGeocodeRequest reverseGeocodeRequest = new ReverseGeocodeRequest();
// Set the credentials using a valid Bing Maps key
reverseGeocodeRequest.Credentials = new GeocodeService.Credentials();
reverseGeocodeRequest.Credentials.ApplicationId = key;
// Set the point to use to find a matching address
GeocodeService.Location point = new GeocodeService.Location();
point.Latitude = latitude;
point.Longitude = longitude;
reverseGeocodeRequest.Location = point;
// Make the reverse geocode request
GeocodeServiceClient geocodeService = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
//This will connect to the server
GeocodeResponse geocodeResponse = geocodeService.ReverseGeocode(reverseGeocodeRequest);
if (geocodeResponse.Results.Length > 0)
results = geocodeResponse.Results[0].DisplayName;
else
results = "No Results found";
address = results;
}} catch{ //here I want to show a msgbox but the problem is, this is not the form class}
Don't catch the exception in that class if there's nothing you can do about it there. Just let it bubble up and catch it where you can do something about it:
public class MyForm : Form
{
public void SomeMethod()
{
try
{
var sc = new ServiceClass();
sc.ReverseGeocodePoint();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
In ReverseGeocodePoint(), remove the try/catch statements.
I am LINQ to input information from a Database. I have my try.catch block set up to catch these exceptions. However I believe I ran into a sore spot where I am attempting to see what the message is but it just bypass printing the message to me and goes directly to error page. Here is an example of the code I have so far. I would love to get some input on why this seems to be acting so strange.
private void CreateEntry()
{
var date = DateTime.Today;
var version = (from v in house.StayLateVersions
where v.Active
select v).FirstOrDefault();
if (version == null)
{
throw new NullReferenceException();
}
//Try to create an entry for the database. Upon failure, sends the exception to ThrowDbError();
try
{
ResidenceHallInspection rhi = new ResidenceHallInspection();
rhi.versionId = version.id;
rhi.submitDate = DateTime.Now;
rhi.CheckInOrOut = ddlCheck.SelectedItem.Text;
rhi.Id = txtId.Text;
rhi.FirstName = txtFirstName.Text;
rhi.MiddleName = txtMiddleName.Text;
rhi.LastName = txtLastName.Text;
rhi.Walls = chbxWalls.SelectedItem.Text;
rhi.Windows = chbxWindows.SelectedItem.Text;
rhi.Blinds = chbxBlinds.SelectedItem.Text;
rhi.Couch = chbxCouch.SelectedItem.Text;
rhi.CommonRoomCouch = chbxCRCouch.SelectedItem.Text;
rhi.CommonRoomChair = chbxCRChair.SelectedItem.Text;
rhi.Doors = chbxDoors.SelectedItem.Text;
rhi.Carpet = chbxCarpet.SelectedItem.Text;
rhi.Ceiling = chbxCeiling.SelectedItem.Text;
rhi.CommonRoomCounter = chbxCRCounter.SelectedItem.Text;
rhi.Cabinet = chbxCabinet.SelectedItem.Text;
rhi.Phone = chbxPhone.SelectedItem.Text;
rhi.Bed = chbxBed.SelectedItem.Text;
rhi.Desk = chbxDesk.SelectedItem.Text;
rhi.DeskChairs = chbxDeskChair.SelectedItem.Text;
rhi.Tub = chbxTub.SelectedItem.Text;
rhi.Vanity = chbxVanity.SelectedItem.Text;
rhi.Notes = txtNotes.Text;
rhi.Building = txtResHall.Text;
rhi.ApartmentNumber = txtSuitNo.Text;
rhi.BedSpace = txtBedSpace.Text;
house.AddToResidenceHallInspections(rhi);
house.SaveChanges();
}
catch (Exception oe)
{
ThrowDbError(oe);
Response.Write(oe.InnerException);
}
}
/*=================================================*/
/*Possible Errors */
/*=================================================*/
private void ThrowDbError(Exception oe)
{
Response.Write(oe.Source);
house.Dispose();
Session.Contents.Add("FormException", oe);
Response.Redirect("/Database-Error/", true);
}
The most likely reason for that to happen is that you are running the database version query outside the try/catch block. Any exception in this db access code will not be handled by the code you have shown above.
Try extending your try block to also include the db access code:
var version = (from v in house.StayLateVersions
where v.Active
select v).FirstOrDefault();
if (version == null)
{
throw new NullReferenceException();
}
and see if this time the error is caught.