The remote server returned an error: (401) Unauthorized - CSOM - OAuth - after specific time - sharepoint

I am trying to get permissions assigned to each document from the document library using csom in console application. Console app is running fine for almost one hour and post that I get error : "The remote server returned an error: (401) Unauthorized."
I registered an app in SharePoint and I'm using Client ID & Client Secret Key to generate Client Context. Here is the code to get the client context
public static ClientContext getClientContext()
{
ClientContext ctx = null;
try
{
ctx = new AuthenticationManager().GetAppOnlyAuthenticatedContext(SiteUrl, ClientId, ClientSecret);
ctx.RequestTimeout = 6000000;
ctx.ExecutingWebRequest += delegate (object sender, WebRequestEventArgs e)
{
e.WebRequestExecutor.WebRequest.UserAgent = "NONISV|Contoso|GovernanceCheck/1.0";
};
}
catch (Exception ex)
{
WriteLog("Method-getClientContext, Error - " + ex.Message);
}
return ctx;
}
Here is the code which is getting all the assignments assigned to document in document library.
static StringBuilder excelData = new StringBuilder();
static void ProcessWebnLists()
{
try
{
string[] lists = { "ABC", "XYZ", "DEF", "GHI"};
foreach (string strList in lists)
{
using (var ctx = getClientContext())
{
if (ctx != null)
{
Web web = ctx.Site.RootWeb;
ListCollection listCollection = web.Lists;
ctx.Load(web);
ctx.Load(listCollection);
ctx.ExecuteQuery();
List list = web.Lists.GetByTitle(strList);
ctx.Load(list);
ctx.ExecuteQuery();
Console.WriteLine("List Name:{0}", list.Title);
var query = new CamlQuery { ViewXml = "<View/>" };
var items = list.GetItems(query);
ctx.Load(items);
ctx.ExecuteQuery();
foreach (var item in items)
{
var itemAssignments = item.RoleAssignments;
ctx.Load(item, i => i.DisplayName);
ctx.Load(itemAssignments);
ctx.ExecuteQuery();
Console.WriteLine(item.DisplayName);
string groupNames = "";
foreach (var assignment in itemAssignments)
{
try
{
ctx.Load(assignment.Member);
ctx.ExecuteQuery();
groupNames += "[" + assignment.Member.Title.Replace(",", " ") + "] ";
Console.WriteLine($"--> {assignment.Member.Title}");
}
catch (Exception e)
{
WriteLog("Method-ProcessWebnLists, List-" + list.Title + ", Document Title - " + item.DisplayName + ", Error : " + e.Message);
WriteLog("Method-ProcessWebnLists, StackTrace : " + e.StackTrace);
}
}
excelData.AppendFormat("{0},{1},ITEM,{2}", list.Title, (item.DisplayName).Replace(",", " "), groupNames);
excelData.AppendLine();
}
}
excelData.AppendLine();
}
}
}
catch (Exception ex)
{
WriteLog("Method-ProcessWebnLists, Error : " + ex.Message);
WriteLog("Method-ProcessWebnLists, StackTrace : " + ex.StackTrace.ToString());
}
}
Can anyone suggest what else I am missing in this or what kind of changes do I need to make to avoid this error?
The process is taking too much time so I want my application to keep running for couple of hours.
Thanks in advance!

Is there a reason why getClientContext() is inside the foreach loop?
I encountered this error before.
I added this to solve mine.
public static void ExecuteQueryWithIncrementalRetry(this ClientContext context, int retryCount, int delay)
{
int retryAttempts = 0;
int backoffInterval = delay;
if (retryCount <= 0)
throw new ArgumentException("Provide a retry count greater than zero.");
if (delay <= 0)
throw new ArgumentException("Provide a delay greater than zero.");
while (retryAttempts < retryCount)
{
try
{
context.ExecuteQuery();
return;
}
catch (WebException wex)
{
var response = wex.Response as HttpWebResponse;
if (response != null && response.StatusCode == (HttpStatusCode)429)
{
Console.WriteLine(string.Format("CSOM request exceeded usage limits. Sleeping for {0} seconds before retrying.", backoffInterval));
//Add delay.
System.Threading.Thread.Sleep(backoffInterval);
//Add to retry count and increase delay.
retryAttempts++;
backoffInterval = backoffInterval * 2;
}
else
{
throw;
}
}
}
throw new MaximumRetryAttemptedException(string.Format("Maximum retry attempts {0}, have been attempted.", retryCount));
}
Basically, this code backs off for a certain time/interval before executing another query, to prevent throttling.
So instead of using ctx.ExecuteQuery(), use ctx.ExecuteQueryWithIncrementalRetry(5, 1000);
Further explanation here
https://learn.microsoft.com/en-us/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online

Related

Workflow C# string function error in Docusign

I have an code issue in docusign.
In my calculation step I have created and input and output code.
When I run the template and checking the "incoming data" xml in the workflow I have an error message displayed:
<In_80_stackTrace>Exception: at ADEXS.DynamicCode.DynamicClassD_3447d8ccd49f4631b91c31df53e249e7.DynamicMethodD_dcb572b7876d400683579290c5918f06(DynamicContext _context)</In_80_stackTrace>
I don't know how to fix this that it will show only the
logError("In_80_error", "Data node //CategoryName is missing");
when no data is in the node.
Below are the details - my input code:
//In_80 - ESP_CategoryName_Description
string In_80 = "";
{
try
{
if (incomingDataRoot.SelectSingleNode("//CategoryName[node()]").InnerText == null)
{
logError("In_80_error", "Data node //CategoryName is missing");
}
else if (incomingDataRoot.SelectSingleNode("//CategoryName[node()]").InnerText != null)
{
In_80 = incomingDataRoot.SelectSingleNode("//CategoryName[node()]").InnerText;
}
}
catch (Exception e)
{
//logError("In_80_error", "Exception: Message:" + e.Message +" Inner Exception: "+ e.InnerException +" StackTrace: "+ e.StackTrace +" Source: "+ e.Source +" Data: "+ e.Data);
logError("In_80_stackTrace", "Exception: " + e.StackTrace);
}
}
Here is the output code:
//OUT_92 - ESP_CategoryName_Description
var OUT_92 = In_80;
if (In_80 == "")
{
logError("OUT_92_error", "Error reading In_80");
} else {
XmlElement elem = incomingDataRoot.OwnerDocument.CreateElement("OUT_92");
string p_category = "";
int i = 1;
foreach (char item in In_80)
{
if (Char.IsLetter(item))
{
if (i == 1)
{
p_category += item.ToString().ToUpper();
}
else
{
p_category += item.ToString().ToLower();
}
i++;
}
else
{
if (item == ' ')
{
i = 1;
}
p_category += item.ToString();
}
}
OUT_92 = p_category;
elem.InnerText = OUT_92.ToString();
elem.SetAttribute("Name", "ESP_CategoryName_Description");
incomingDataRoot.SelectSingleNode("/Root/Params/TemplateFieldData/Calculation_Results").AppendChild(elem);
}
In incoming data OUT part I'm getting
<OUT_92_error>Error reading In_80</OUT_92_error>
where I assume that its because something is wrong with the input code part?
Thank you for your help!

How to get Logic App Metrics?

I'm trying to get Logic Apps metrics like BillableExecutions, Latency etc in my console application.
Currently I'm able to list the logic apps runs, triggers, versions using the .Net Client Microsoft.Azure.Management. But it doesn't seem to have the API to access the monitoring API's.
Code excerpt
private static void Main(string[] args)
{
var token = GetTokenCredentials();
var client = new LogicManagementClient(token, new HttpClientHandler())
{
SubscriptionId = new AzureSubscription().SubscriptionId
};
var dataQuery = new ODataQuery<WorkflowFilter>
{
Top = 50
};
using (client)
{
var logicAppsWorkFlows = client.Workflows.ListBySubscription(dataQuery);
foreach (var logicAppsWorkFlow in logicAppsWorkFlows)
{
var runs = GetWorkflowRuns(client, logicAppsWorkFlow.Id.Split('/')[4], logicAppsWorkFlow.Name);
Console.WriteLine(runs.Count);
}
Console.WriteLine(logicAppsWorkFlows.Count());
}
}
Can someone tell me how to access Logic Apps Metrics? Is there a client similar to Microsoft.Azure.Management for access metrics data?
Update 2
I have found a client dll which was in pre release mode which is used to get metrics. Below is my current code
var token = GetTokenCredentials();
var insightsClient = new InsightsClient(token, new HttpClientHandler())
{
SubscriptionId = new AzureSubscription().SubscriptionId
};
var logicManagementClient = new LogicManagementClient(token, new HttpClientHandler())
{
SubscriptionId = new AzureSubscription().SubscriptionId
};
var dataQuery = new ODataQuery<WorkflowFilter>
{
Top = 50
};
using (logicManagementClient)
{
var logicAppsWorkFlows = logicManagementClient.Workflows.ListBySubscription(dataQuery);
foreach (var logicAppsWorkFlow in logicAppsWorkFlows)
{
using (insightsClient)
{
var metricsDataQuery = new ODataQuery<Metric>
{
Filter = "name.value eq 'ActionLatency' and startTime ge '2014-07-16'"
};
IEnumerable<Metric> metricsList = null;
try
{
metricsList = insightsClient.Metrics.List(logicAppsWorkFlow.Id, metricsDataQuery);
}
catch (Exception e)
{
Console.WriteLine(e);
}
if (metricsList == null) continue;
foreach (var metric in metricsList)
{
foreach (var metricValue in metric.Data)
{
Console.WriteLine(metric.Name.Value + " = " + metricValue.Total);
}
}
}
}
}
I'm getting an exception saying the filter string is not valid. Im referring the filter string structure provided here
https://learn.microsoft.com/en-us/rest/api/monitor/filter-syntax
Can someone tell what im doing wrong here?
Thanks
It looks like ge is not allowed for Logic Apps StartTime field for some reason. I had to change the code to below to make it work
using (logicManagementClient)
{
var logicAppsWorkFlows = logicManagementClient.Workflows.ListBySubscription(dataQuery);
foreach (var logicAppsWorkFlow in logicAppsWorkFlows)
{
using (insightsClient)
{
var metricsDataQuery = new ODataQuery<Metric>
{
Filter = "startTime eq " + DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd") + " and name.value eq 'BillableTriggerExecutions' and endTime eq " + DateTime.Now.ToString("yyyy-MM-dd")
};
var query = metricsDataQuery.GetQueryString();
Console.WriteLine(query);
IEnumerable<Metric> metricsList = null;
try
{
//throws exception if there is no metrics data
//TODO: Check whether the logic app ran atleast one time
metricsList = insightsClient.Metrics.List(logicAppsWorkFlow.Id, metricsDataQuery);
}
catch (Exception e)
{
Console.WriteLine(e);
}
if (metricsList == null) continue;
foreach (var metric in metricsList)
{
foreach (var metricValue in metric.Data)
{
Console.WriteLine(metric.Name.Value + " = " + metricValue.Total);
}
}
}
}
}

How to return Json response message for http error like 404 in wcf Service?

I have the below function which i am returning employees list. If
there is no list present in DB, I need to return httpstatusErrorcode
with error message
public List<SelectEventsMClass> FetchAllEmployes(int EmployTypeID)
{
try
{
var EventsList = new List<SelectEventsMClass>();
Employ.Data.EmployTableAdapters.EventsMSelectAllTableAdapter Adp = new Data.EmployTableAdapters.EventsMSelectAllTableAdapter();
Employ.Data.Employ.EventsMSelectAllDataTable Dtl = Adp.GetData(intEventTypeID);
if (Dtl.Rows.Count > 0)
{
var EventsList = (from lst in Dtl.AsEnumerable()
select new SelectEventsMClass
{
TransID = lst.Field<Guid>("TransID"),
SchoolTransID = lst.Field<Guid>("SchoolTransID"),
AcadamicTransID = lst.Field<Guid>("AcadamicTransID"),
EventTypeID = lst.Field<int>("EventTypeID"),
EventTitle = lst.Field<string>("EventTitle"),
}).ToList();
}
return EventsList;
}
catch (Exception ex)
{
throw ex;
}
}

Error while adding entity object to DBContext object called from Parallel.Foreach loop

Error :
If the event originated on another computer, the display information had to be saved with the event.
The following information was included with the event:
Object reference not set to an instance of an object. at
System.Data.Objects.ObjectStateManager.DetectConflicts(IList1
entries) at System.Data.Objects.ObjectStateManager.DetectChanges()
at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean
force) at
System.Data.Entity.Internal.Linq.InternalSet1.ActOnSet(Action action,
EntityState newState, Object entity, String methodName) at
System.Data.Entity.Internal.Linq.InternalSet1.Add(Object entity)
at System.Data.Entity.DbSet1.Add(TEntity entity) at
ESHealthCheckService.BusinessFacade.BusinessOperationsLayer.AddErrorToDbObject(Exception
ex, Server serverObj, Service windowsServiceObj)
the message resource is present but the message is not found in the string/message table
public void CheckForServerHealth()
{
businessLayerObj.SetStartTimeWindowsService();
List<ServerMonitor> serverMonitorList = new List<ServerMonitor>();
serverList = businessLayerObj.GetServerList();
Parallel.ForEach(
serverList,
() => new List<ServerMonitor>(),
(server, loop, localState) =>
{
localState.Add(serverStatus(server, new ServerMonitor()));
return localState;
},
localState =>
{
lock (serverMonitorList)
{
foreach (ServerMonitor serverMonitor in localState)
{
serverMonitorList.Add(serverMonitor);
}
}
});
businessLayerObj.SaveServerHealth(serverMonitorList);
}
public ServerMonitor serverStatus(Server serverObj, ServerMonitor serverMonitorObj)
{
if (new Ping().Send(serverObj.ServerName, 30).Status == IPStatus.Success)
{
serverMonitorObj.Status = true;
try
{
PerformanceCounter cpu = new PerformanceCounter("Processor", "% Processor Time", "_Total", serverObj.ServerName);
serverMonitorObj.CPUUtlilization = (cpu.NextValue());
}
catch (Exception ex)
{
businessLayerObj.AddErrorObjectToStaticList(ex, serverObj);
}
serverMonitorObj.ServerID = serverObj.ServerID;
try
{
string[] diskArray = serverObj.DriveMonitor.ToString().Split(':');
if (diskArray != null && diskArray.Contains("NA"))
{
serverMonitorObj.DiskSpace = "NA";
}
else
{
serverMonitorObj.DiskSpace = ReadFreeSpaceOnNetworkDrives(serverObj.ServerName, diskArray);
}
}
catch (Exception ex)
{
businessLayerObj.AddErrorObjectToStaticList(ex, serverObj);
}
serverMonitorObj.CreatedDateTime = DateTime.Now;
}
else
{
serverMonitorObj.Status = false;
serverMonitorObj.ServerID = serverObj.ServerID;
//return serverMonitorObj;
}
return serverMonitorObj;
}
public void AddErrorObjectToStaticList(Exception ex, Server serverObj = null, Service windowsServiceObj = null)
{
EShelathLoging esLogger = new EShelathLoging();
esLogger.CreateDatetime = DateTime.Now;
if (ex.InnerException != null)
{
esLogger.Message = (windowsServiceObj == null ? ex.InnerException.Message : ("Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.InnerException.Message));
//esLogger.Message = "Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.InnerException.Message;
esLogger.StackTrace = (ex.InnerException.StackTrace == null ? "" : ex.InnerException.StackTrace);
}
else
{
esLogger.Message = (windowsServiceObj == null ? ex.Message : ("Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.Message));
//esLogger.Message = "Service Name : " + windowsServiceObj.ServiceName + "-->" + ex.Message;
esLogger.StackTrace = ex.StackTrace;
}
if (serverObj != null)
{
esLogger.ServerName = serverObj.ServerName;
}
try
{
lock (lockObject)
{
esHealthCheckLoggingList.Add(esLogger);
}
}
catch (Exception exe)
{
string logEntry = "Application";
if (EventLog.SourceExists(logEntry) == false)
{
EventLog.CreateEventSource(logEntry, "Windows and IIS health check Log");
}
EventLog eventLog = new EventLog();
eventLog.Source = logEntry;
eventLog.WriteEntry(exe.Message + " " + exe.StackTrace, EventLogEntryType.Error);
}
}
And then the below function is called to add objects from static list to the db object.
public void AddErrorToDbObject()
{
try
{
foreach (EShelathLoging eslogObject in esHealthCheckLoggingList)
{
lock (lockObject)
{
dbObject.EShelathLogings.Add(eslogObject);
}
}
}
catch (DbEntityValidationException exp)
{
string logEntry = "Application";
if (EventLog.SourceExists(logEntry) == false)
{
EventLog.CreateEventSource(logEntry, "Windows and IIS health check Log");
}
EventLog eventLog = new EventLog();
eventLog.Source = logEntry;
eventLog.WriteEntry(exp.Message + " " + exp.StackTrace, EventLogEntryType.Error);
}
catch (Exception exe)
{
string logEntry = "Application";
if (EventLog.SourceExists(logEntry) == false)
{
EventLog.CreateEventSource(logEntry, "Windows and IIS health check Log");
}
EventLog eventLog = new EventLog();
eventLog.Source = logEntry;
eventLog.WriteEntry(exe.Message + " " + exe.StackTrace, EventLogEntryType.Error);
}`enter code here`
}
DbSet<T> is not thread-safe, so you can't use it from multiple threads at the same time. It seems you're trying to fix that by using a lock, but you're doing that incorrectly. For this to work, all threads have to share a single lock object. Having separate lock object for each thread, like you do now, won't do anything.
Please note that I received the same exception with the application I was working on, and determined that the best way to resolve the issue was to add an AsyncLock, because of what #svick mentioned about how DbSet is not threadsafe. Thank you, #svick!
I'm guessing that your DbContext is inside your businessLayerObj, so here is what I recommend, using Stephen Cleary's excellent Nito.AsyncEx (see https://www.nuget.org/packages/Nito.AsyncEx/):
using Nito.AsyncEx;
// ...
private readonly AsyncLock _dbContextMutex = new AsyncLock();
public void CheckForServerHealth()
{
using (await _dbContextMutex.LockAsync().ConfigureAwait(false))
{
await MyDbContextOperations(businessLayerObj).ConfigureAwait(false);
}
}
private async Task MyDbContextOperations(BusinessLayerClass businessLayerObj)
{
await Task.Run(() =>
{
// operations with businessLayerObj/dbcontext here...
});
}

Not able to get DirContext ctx using Spring Ldap

Hi i am using Spring ldap , after execution below program It display I am here only and after that nothing is happening, program is in continue execution mode.
public class SimpleLDAPClient {
public static void main(String[] args) {
Hashtable env = new Hashtable();
System.out.println("I am here");
String principal = "uid="+"a502455"+", ou=People, o=ao, dc=com";
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "MYURL");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, principal);
env.put(Context.SECURITY_CREDENTIALS,"PASSWORD");
DirContext ctx = null;
NamingEnumeration results = null;
try {
ctx = new InitialDirContext(env);
System.out.println(" Context" + ctx);
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=aoPerson)", controls);
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
Attributes attributes = searchResult.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
System.out.println(" Person Common Name = " + cn);
}
} catch (NamingException e) {
throw new RuntimeException(e);
} finally {
if (results != null) {
try {
results.close();
} catch (Exception e) {
}
}
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
}
}
}
}
}
Try fixing the below lines, i removed "ao" and it works fine.
results = ctx.search("", "(objectclass=Person)", controls);
You need to give search base as well
env.put(Context.PROVIDER_URL, "ldap://xx:389/DC=test,DC=enterprise,DC=xx,DC=com");
Refer this link as well http://www.adamretter.org.uk/blog/entries/LDAPTest.java

Resources