How to debug a viewstate validation error in DNN? - webforms

I have a DotNetNuke application that I inherited and I'm trying to make some updates to an existing module. It happens to be a custom login module.
I'm trying to integrate 2 factor authentication. The login itself works, but when I then want to display the 2 factor fields after that, I get a 503 error on submission of the 2 factor code.
I tried to add an Application_Error event in global.asax, but that was never hit. I also tried to override the OnError event of the login control, but that is also never hit.
The OnInit is always hit during the postback that produces the 503, but not OnLoad. The strangest part is that if I step over each line of the OnInit, until I hit first thing outside of OnInit and then click Continue, everything works fine. If I just click Continue from the breakpoint at the beginning of OnInit, it will fail with a 503 before getting to OnLoad, almost every time.
This points to some kind of asynchronous error but I can't imagine what it might be.
The login versus 2 factor fields are shown and hidden by Panel controls if that makes any difference.
The message that comes back with the 503 error is "No sites currently exist for this installation."
Any suggestions on how to narrow down what's causing the 503 are greatly appreciated.
Update
I missed a log entry for a viewstate validation exception.
Validation of viewstate MAC failed. If this application is hosted by a Web
Farm or cluster, ensure that configuration specifies the same validationKey
and validation algorithm. AutoGenerate cannot be used in a cluster.
See http://go.microsoft.com/fwlink/?LinkID=314055 for more information.
I set the machine key values, but I still get the same error. Not to mention that it also doesn't explain why this only happens if I don't step through OnInit
Any thoughts?

It turns out that my problem stemmed from calling UserController.UserLogin() prior to trying to verify the 2 factor authentication.
Now that I'm calling that after the 2 factor verification, everything works as expected, and even consistently :o)
Code
Here's a sample of what changed.
This is what didn't work:
private void ValidateUser(UserInfo objUser, bool ignoreExpiring)
{
UserValidStatus validStatus = UserValidStatus.VALID;
string strMessage = Null.NullString;
DateTime expiryDate = Null.NullDate;
bool okToShowPanel = true;
validStatus = UserController.ValidateUser(objUser, PortalId, ignoreExpiring);
if (PasswordConfig.PasswordExpiry > 0)
{
expiryDate = objUser.Membership.LastPasswordChangeDate.AddDays(PasswordConfig.PasswordExpiry);
}
UserId = objUser.UserID;
//Check if the User has valid Password/Profile
switch (validStatus)
{
case UserValidStatus.VALID:
//check if the user is an admin/host and validate their IP
if (Host.EnableIPChecking)
{
bool isAdminUser = objUser.IsSuperUser || PortalSettings.UserInfo.IsInRole(PortalSettings.AdministratorRoleName); ;
if (isAdminUser)
{
if (IPFilterController.Instance.IsIPBanned(Request.UserHostAddress))
{
new PortalSecurity().SignOut();
AddModuleMessage("IPAddressBanned", ModuleMessage.ModuleMessageType.RedError, true);
okToShowPanel = false;
break;
}
}
}
//Set the Page Culture(Language) based on the Users Preferred Locale
if ((objUser.Profile != null) && (objUser.Profile.PreferredLocale != null))
{
Localization.SetLanguage(objUser.Profile.PreferredLocale);
}
else
{
Localization.SetLanguage(PortalSettings.DefaultLanguage);
}
//Set the Authentication Type used
AuthenticationController.SetAuthenticationType(AuthenticationType);
var userRequestIPAddress = new UserRequestIPAddressController();
//Complete Login
UserController.UserLogin(PortalId, objUser, PortalSettings.PortalName, userRequestIPAddress.GetUserRequestIPAddress(new HttpRequestWrapper(Request)), RememberMe);
var twoFactorAuthStatus = GetTwoFactorAuthStatus(objUser);
switch (twoFactorAuthStatus)
{
case TwoFactorAuthStatus.Error:
return;
case TwoFactorAuthStatus.NotEnabled:
RedirectUser(objUser);
break;
case TwoFactorAuthStatus.SetupNeeded:
PageNo = googleAuthSetupPageNo;
break;
case TwoFactorAuthStatus.VerificationNeeded:
PageNo = verifyGoogleAuthPageNo;
break;
}
break;
case UserValidStatus.PASSWORDEXPIRED:
strMessage = string.Format(Localization.GetString("PasswordExpired", LocalResourceFile), expiryDate.ToLongDateString());
AddLocalizedModuleMessage(strMessage, ModuleMessage.ModuleMessageType.YellowWarning, true);
PageNo = passwordPageNo;
pnlProceed.Visible = false;
break;
case UserValidStatus.PASSWORDEXPIRING:
strMessage = string.Format(Localization.GetString("PasswordExpiring", LocalResourceFile), expiryDate.ToLongDateString());
AddLocalizedModuleMessage(strMessage, ModuleMessage.ModuleMessageType.YellowWarning, true);
PageNo = passwordPageNo;
pnlProceed.Visible = true;
break;
case UserValidStatus.UPDATEPASSWORD:
AddModuleMessage("PasswordUpdate", ModuleMessage.ModuleMessageType.YellowWarning, true);
PageNo = passwordPageNo;
pnlProceed.Visible = false;
break;
case UserValidStatus.UPDATEPROFILE:
//Save UserID in ViewState so that can update profile later.
UserId = objUser.UserID;
//When the user need update its profile to complete login, we need clear the login status because if the login is from
//3rd party login provider, it may call UserController.UserLogin because they doesn't check this situation.
new PortalSecurity().SignOut();
//Admin has forced profile update
AddModuleMessage("ProfileUpdate", ModuleMessage.ModuleMessageType.YellowWarning, true);
PageNo = profilePageNo;
break;
}
if (okToShowPanel) ShowPanel();
}
This is what worked:
private void ValidateUser(UserInfo objUser, bool ignoreExpiring)
{
UserValidStatus validStatus = UserValidStatus.VALID;
string strMessage = Null.NullString;
DateTime expiryDate = Null.NullDate;
bool okToShowPanel = true;
validStatus = UserController.ValidateUser(objUser, PortalId, ignoreExpiring);
if (PasswordConfig.PasswordExpiry > 0)
{
expiryDate = objUser.Membership.LastPasswordChangeDate.AddDays(PasswordConfig.PasswordExpiry);
}
UserId = objUser.UserID;
//Check if the User has valid Password/Profile
switch (validStatus)
{
case UserValidStatus.VALID:
//check if the user is an admin/host and validate their IP
if (Host.EnableIPChecking)
{
bool isAdminUser = objUser.IsSuperUser || PortalSettings.UserInfo.IsInRole(PortalSettings.AdministratorRoleName); ;
if (isAdminUser)
{
if (IPFilterController.Instance.IsIPBanned(Request.UserHostAddress))
{
new PortalSecurity().SignOut();
AddModuleMessage("IPAddressBanned", ModuleMessage.ModuleMessageType.RedError, true);
okToShowPanel = false;
break;
}
}
}
var twoFactorAuthStatus = GetTwoFactorAuthStatus(objUser);
switch (twoFactorAuthStatus)
{
case TwoFactorAuthStatus.Error:
return;
case TwoFactorAuthStatus.NotEnabled:
LoginUser(objUser);
break;
case TwoFactorAuthStatus.SetupNeeded:
PageNo = googleAuthSetupPageNo;
break;
case TwoFactorAuthStatus.VerificationNeeded:
PageNo = verifyGoogleAuthPageNo;
break;
}
break;
case UserValidStatus.PASSWORDEXPIRED:
strMessage = string.Format(Localization.GetString("PasswordExpired", LocalResourceFile), expiryDate.ToLongDateString());
AddLocalizedModuleMessage(strMessage, ModuleMessage.ModuleMessageType.YellowWarning, true);
PageNo = passwordPageNo;
pnlProceed.Visible = false;
break;
case UserValidStatus.PASSWORDEXPIRING:
strMessage = string.Format(Localization.GetString("PasswordExpiring", LocalResourceFile), expiryDate.ToLongDateString());
AddLocalizedModuleMessage(strMessage, ModuleMessage.ModuleMessageType.YellowWarning, true);
PageNo = passwordPageNo;
pnlProceed.Visible = true;
break;
case UserValidStatus.UPDATEPASSWORD:
AddModuleMessage("PasswordUpdate", ModuleMessage.ModuleMessageType.YellowWarning, true);
PageNo = passwordPageNo;
pnlProceed.Visible = false;
break;
case UserValidStatus.UPDATEPROFILE:
//Save UserID in ViewState so that can update profile later.
UserId = objUser.UserID;
//When the user need update its profile to complete login, we need clear the login status because if the login is from
//3rd party login provider, it may call UserController.UserLogin because they doesn't check this situation.
new PortalSecurity().SignOut();
//Admin has forced profile update
AddModuleMessage("ProfileUpdate", ModuleMessage.ModuleMessageType.YellowWarning, true);
PageNo = profilePageNo;
break;
}
if (okToShowPanel) ShowPanel();
}
I changed RedirectUser() from the first example, to a LoginUser() that also performs the redirect. The LoginUser() is also called after a successful 2 factor authentication and/or setup as well.
This is a more secure way to handle this in general. The debugging feedback I was receiving was just super frustratingly misleading.

Related

Keeping Data between refreshes in Blazor server

I have a multiple page Web Application that needs to be refreshed after a user has entered in data to then display the data on the table. I have Scoped dependencies so my users do not see the same data table as they are unique to each user. After they enter the data and the page refreshes the page goes blank and the scope is empty. How would I go about keeping the data from the scopes after refresh? I essentially needs a Singlton dependency that isn't shared between users. This is a Blazor Server Side Application. EDIT: Accept Button Method
if (Controlled_Variables.Attendance != null)
{
if (_JBS.CheckFields(_JBF.JobID, _JBF.WorkCenter, _JBF.SetupRun) == false)
{
string prompted = await jsRunTime.InvokeAsync<string>("alert", "Please Verify Job ID, Work Center, and Setup/Run are selected!");
}
else
{
FilledOut = true;
_JBF.transactionData = Guid.NewGuid();
_JBF.jobOperationID = _JBF.WorkCenter;
DateTime recordDate = DateTime.Now;
JobOperationRecord JOR = await _JBS.GetJobOperationRecordByOperationID(_JBF.WorkCenter);
WorkCenterRecord SingleWorkCenter = await _JBS.GetWorkCenterInformation(JOR.Work_Center);
EmployeeRecord Employee = await _JBS.GetEmployeeRecord(Controlled_Variables.Employee_ID);
try
{
if (Check.IsThisAnActiveJob(_JBF.JobID))
{
bool Complete = await First_Article_Complete(_JBF.jobOperationID, _JBF.SetupRun);
if (Complete)
{
Controlled_Variables.Sessions.Clear();
Controlled_Variables.Sessions = await _JBS.GetOpenJobOperationTimeSessionForUser(Controlled_Variables.Employee_ID);
bool activeNonGhostSession = false;
foreach (JobOperationSessionManager Session in Controlled_Variables.Sessions)
{
if (Session.ghost == "Y")
{
Controlled_Variables.ActiveSession = Session;
activeNonGhostSession = true;
}
}
_JBS.UpdateJobOperationStatus(JOR.Job_Operation.ToString(), JOR.Status == "C" ? "C" : "S");
if (!activeNonGhostSession && !_JBF.GhostedCheck)
{
_JBS.AddNewJobOperationTimeSessionForUser(Controlled_Variables.Employee_ID, "N", _JBF.transactionData.ToString(), JOR.Work_Center,
_JBF.jobOperationID, _JBF.JobID, recordDate.ToString("yyyy-MM-dd HH:mm:ss"), _JBF.jobOperationTime.ToString(), _JBF.SetupRun);
_JBF.sessionManagerCreated = true;
_JBS.InsertIntoTransactionDetail_NewEntry_JobOperation(_JBF.transactionData.ToString(), _JBF.jobOperationID, _JBF.jobOperationTime.ToString(),
JOR.Work_Center, _JBF.JobID);
_JBF.transDetailCreated = true;
_JBS.InsertIntoTransactionData_NewEntry_JobOperation(_JBF.transactionData.ToString(), Controlled_Variables.Employee_ID, recordDate.ToString());
_JBF.transDataCreated = true;
_JBS.InsertIntoJobOperationTime_NewEntry_JobOperationStart(_JBF.jobOperationID, Controlled_Variables.Employee_ID, recordDate.ToString(),
Employee.Hourly_Rate.ToString(), SingleWorkCenter.Labor_Burden.ToString(), SingleWorkCenter.Machine_Burden.ToString(), SingleWorkCenter.GA_Burden.ToString(),
_JBF.jobOperationTime.ToString(), JOR.Work_Center, _JBF.jobOperationTimeObjectID.ToString(), JOR.ObjectID.ToString(), Employee.ObjectID.ToString());
_JBF.jobOperationTimeCreated = true;
btnStartJob = true;
btnStopJob = false;
NavManage.NavigateTo(NavManage.Uri, forceLoad: true);
string prompted = await jsRunTime.InvokeAsync<string>("alert", "The job has been entered successfully.", "ERROR");
Sorry for the confusion for the use of refresh. I needed to reload the table to allow the data put in by users to be visable after they hit accept. To do this I added a navigation manager
NavManage.NavigateTo(NavManage.Uri, forceLoad: true);
Which force loads the page and displays the new data. If there may be another way to do this to keep the scope I am open to using a different method. As you can see I have tried to just recall the method in which the table data is loaded into to possibly get the new data populated but then the application never reiterates the loop to actually display the data on the page
#for (int i = 0; i < Controlled_Variables.TransactionData.Count; i++)
{
var TransacData = Controlled_Variables.TransactionData[i];
TransacData.index = i;
#for (int l = 0; l < Controlled_Variables.TransactionDetail.Count; l++)
{
var transacdetail = Controlled_Variables.TransactionDetail[l];
transacdetail.index = l;
TransactionDetailRecord selectData = Controlled_Variables.TransactionDetail[l];
#if (transacdetail.Transaction_Data == TransacData.Transaction_Data)
{
<div><input value="#selectData" type="radio" name="Select" onclick="#(() => ShowSelectedRecord(selectData, TransacData))"> </div>
<div>#transacdetail.Target_Integer</div>
<div>#transacdetail.Job</div>
<div>#Controlled_Variables.Job.Part_Number</div>
<div>#TransacData.Transaction_Start</div>
if (TransacData.Transaction_Type == 10)
{
<div>#TransacData.Transaction_Type</div>
btnStartJob = true;
btnStopJob = false;
}
else
{
<div>#TransacData.Transaction_Type</div>
btnStartJob = false;
btnStopJob = true;
}
<div>#Controlled_Variables.Job.Customer</div>
<div>#transacdetail.Work_Center</div>
<div>#transacdetail.Quantity</div>
<div>#TransacData.Transaction_End</div>
<div>#transacdetail.Entry_Type</div>
<div>#transacdetail.Labor_Hrs</div>
<div>#transacdetail.Machine_Hrs</div>
<div>#TransacData.Transaction_Data</div>
<div>#transacdetail.Transaction_Detail</div>
}
}
}

CRM SDK 2013 Activity doesn't exist just after creating it

I have a custom comment activity which I'm updating in code and this used to work but has started failing recently. It creates the activity but when I try to retrieve it or execute SetStateResponse on it, I get "tk_comment With Id = 9a1686d1-7d9d-e611-80e3-00155d001104 Does Not Exist" - which doesn't make sense as I've just created it! The activity record shows up against the account but I can't click on it there or do anything (Record is unavailable - The requested record was not found or you do not have sufficient permissions to view it.).
This is the code I'm using. I'd love you to tell me I've made some simple mistake :)
using (_serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig))
{
_serviceProxy.EnableProxyTypes();
try
{
tk_comment comment = new tk_comment();
int maxLength = 190; //subject has a max length of 200 characters
if (subject.Length > maxLength)
{
comment.Subject = subject.Substring(0, maxLength);
comment.Description = subject.Substring(maxLength, subject.Length - maxLength);
}
else
{
comment.Subject = subject;
}
comment.RegardingObjectId = entity.ToEntityReference();
comment.ActualStart = CommentDate;
comment.ActualEnd = CommentDate;
comment.ScheduledStart = CommentDate;
comment.ScheduledEnd = CommentDate;
Guid commentID = _serviceProxy.Create(comment);
try
{
tk_comment aComment = (tk_comment)_serviceProxy.Retrieve(tk_comment.EntityLogicalName, commentID, new ColumnSet(allColumns: true));
}
catch (Exception ex)
{
SingletonLogger.Instance.Error("Always an error here " + ex.Message);
}
Account test = (Account) _serviceProxy.Retrieve(Account.EntityLogicalName, entity.Id, new ColumnSet(allColumns: true));
// tk_comment newComment = (tk_comment)_serviceProxy.Retrieve(tk_comment.EntityLogicalName, commentID, new ColumnSet(allColumns: true));
SetStateRequest request = new SetStateRequest();
request.EntityMoniker = new EntityReference(tk_comment.EntityLogicalName, commentID);
request.State = new OptionSetValue((int) tk_commentState.Completed); //completed
request.Status = new OptionSetValue(2); //completed
SetStateResponse response = (SetStateResponse)_serviceProxy.Execute(request); //always an error here too
}
Appreciate any suggestions
Cheers, Mick
It seems like you don't have proper read permission of this custom activity entity.
OR You need to validate all the permissions of this custom entity.

How to retrieve all contacts from Microsoft Exchange using EWS Managed API?

all I need to do is to retrieve all contacts from Microsoft Exchange. I did some research and the best possible option for me should be to use EWS Managed API. I am using Visual Studio and C# programming leanguage.
I think I am able to connect to Office365 account, because I am able to send a message in a program to specific email. But I am not able to retrieve the contacts.
If I create a contact directly in source code, the contact will be created in Office365->People aplication. But I don't know why! I thought I was working with Exchange aplication.
Summarize:
Is there any possibility how to get all contacts from Office365->Admin->Exchange->Acceptencers->Contacts ?
Here is my code:
class Program
{
static void Main(string[] args)
{
// connecting to my Exchange account
ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials("office365email#test.com", "password123");
/*
// debugging
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
*/
service.AutodiscoverUrl("office365email#test.com", RedirectionUrlValidationCallback);
// send a message works good
EmailMessage email = new EmailMessage(service);
email.ToRecipients.Add("matoskok1#gmail.com");
email.Subject = "HelloWorld";
email.Body = new MessageBody("Toto je testovaci mail");
email.Send();
// Create the contact creates a contact in Office365 -> People application..Don't know why there and not in Office365 -> Exchange
/*Contact contact = new Contact(service);
// Specify the name and how the contact should be filed.
contact.GivenName = "Brian";
contact.MiddleName = "David";
contact.Surname = "Johnson";
contact.FileAsMapping = FileAsMapping.SurnameCommaGivenName;
// Specify the company name.
contact.CompanyName = "Contoso";
// Specify the business, home, and car phone numbers.
contact.PhoneNumbers[PhoneNumberKey.BusinessPhone] = "425-555-0110";
contact.PhoneNumbers[PhoneNumberKey.HomePhone] = "425-555-0120";
contact.PhoneNumbers[PhoneNumberKey.CarPhone] = "425-555-0130";
// Specify two email addresses.
contact.EmailAddresses[EmailAddressKey.EmailAddress1] = new EmailAddress("brian_1#contoso.com");
contact.EmailAddresses[EmailAddressKey.EmailAddress2] = new EmailAddress("brian_2#contoso.com");
// Specify two IM addresses.
contact.ImAddresses[ImAddressKey.ImAddress1] = "brianIM1#contoso.com";
contact.ImAddresses[ImAddressKey.ImAddress2] = " brianIM2#contoso.com";
// Specify the home address.
PhysicalAddressEntry paEntry1 = new PhysicalAddressEntry();
paEntry1.Street = "123 Main Street";
paEntry1.City = "Seattle";
paEntry1.State = "WA";
paEntry1.PostalCode = "11111";
paEntry1.CountryOrRegion = "United States";
contact.PhysicalAddresses[PhysicalAddressKey.Home] = paEntry1;
// Specify the business address.
PhysicalAddressEntry paEntry2 = new PhysicalAddressEntry();
paEntry2.Street = "456 Corp Avenue";
paEntry2.City = "Seattle";
paEntry2.State = "WA";
paEntry2.PostalCode = "11111";
paEntry2.CountryOrRegion = "United States";
contact.PhysicalAddresses[PhysicalAddressKey.Business] = paEntry2;
// Save the contact.
contact.Save();
*/
// msdn.microsoft.com/en-us/library/office/jj220498(v=exchg.80).aspx
// Get the number of items in the Contacts folder.
ContactsFolder contactsfolder = ContactsFolder.Bind(service, WellKnownFolderName.Contacts);
Console.WriteLine(contactsfolder.TotalCount);
// Set the number of items to the number of items in the Contacts folder or 50, whichever is smaller.
int numItems = contactsfolder.TotalCount < 50 ? contactsfolder.TotalCount : 50;
// Instantiate the item view with the number of items to retrieve from the Contacts folder.
ItemView view = new ItemView(numItems);
// To keep the request smaller, request only the display name property.
view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ContactSchema.DisplayName);
// Retrieve the items in the Contacts folder that have the properties that you selected.
FindItemsResults<Item> contactItems = service.FindItems(WellKnownFolderName.Contacts, view);
// Display the list of contacts.
foreach (Item item in contactItems)
{
if (item is Contact)
{
Contact contact1 = item as Contact;
Console.WriteLine(contact1.DisplayName);
}
}
Console.ReadLine();
} // end of Main() method
/*===========================================================================================================*/
private static bool CertificateValidationCallBack(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
// If the certificate is a valid, signed certificate, return true.
if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
return true;
}
// If there are errors in the certificate chain, look at each error to determine the cause.
if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
if (chain != null && chain.ChainStatus != null)
{
foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
{
if ((certificate.Subject == certificate.Issuer) &&
(status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
{
// Self-signed certificates with an untrusted root are valid.
continue;
}
else
{
if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
{
// If there are any other errors in the certificate chain, the certificate is invalid,
// so the method returns false.
return false;
}
}
}
}
// When processing reaches this line, the only errors in the certificate chain are
// untrusted root errors for self-signed certificates. These certificates are valid
// for default Exchange server installations, so return true.
return true;
}
else
{
// In all other cases, return false.
return false;
}
}
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
}
seems like you are already doing a good job doing a FindItems() method.
In order to get all contacts all you need to add is a SearchFilter, in this case I'd recommend doing the Exists() filter as you can simply say Find All contacts with an id.
See my example below if you need an example of a Full Windows Application dealing with contacts see my github page github.com/rojobo
Dim oFilter As New SearchFilter.Exists(ItemSchema.Id)
Dim oResults As FindItemsResults(Of Item) = Nothing
Dim oContact As Contact
Dim blnMoreAvailable As Boolean = True
Dim intSearchOffset As Integer = 0
Dim oView As New ItemView(conMaxChangesReturned, intSearchOffset, OffsetBasePoint.Beginning)
oView.PropertySet = BasePropertySet.IdOnly
Do While blnMoreAvailable
oResults = pService.FindItems(WellKnownFolderName.Contacts, oFilter, oView)
blnMoreAvailable = oResults.MoreAvailable
If Not IsNothing(oResults) AndAlso oResults.Items.Count > 0 Then
For Each oExchangeItem As Item In oResults.Items
Dim oExchangeContactId As ItemId = oExchangeItem.Id
//do something else
Next
If blnMoreAvailable Then oView.Offset = oView.Offset + conMaxChangesReturned
End If
Loop
How to retrieve all contacts from Microsoft Exchange using EWS Managed API?
If your question is how to retrieve the Exchange Contacts using EWS, you're already done with it.
Office365->People is just the right app to manipulate your Exchange contacts. If you check out the People app URL, it's something similar to https://outlook.office365.com/owa/?realm=xxxxxx#exsvurl=1&ll-cc=1033&modurl=2, owa is the synonym for outlook web app.

EWS The server cannot service this request right now

I am seeing errors while exporting email in office 365 account using ews managed api, "The server cannot service this request right now. Try again later." Why is that error occurring and what can be done about it?
I am using the following code for that work:-
_GetEmail = (EmailMessage)item;
bool isread = _GetEmail.IsRead;
sub = _GetEmail.Subject;
fold = folder.DisplayName;
historicalDate = _GetEmail.DateTimeSent.Subtract(folder.Service.TimeZone.GetUtcOffset(_GetEmail.DateTimeSent));
props = new PropertySet(EmailMessageSchema.MimeContent);
var email = EmailMessage.Bind(_source, item.Id, props);
bytes = new byte[email.MimeContent.Content.Length];
fs = new MemoryStream(bytes, 0, email.MimeContent.Content.Length, true);
fs.Write(email.MimeContent.Content, 0, email.MimeContent.Content.Length);
Demail = new EmailMessage(_destination);
Demail.MimeContent = new MimeContent("UTF-8", bytes);
// 'SetExtendedProperty' used to maintain historical date of items
Demail.SetExtendedProperty(new ExtendedPropertyDefinition(57, MapiPropertyType.SystemTime), historicalDate);
// PR_MESSAGE_DELIVERY_TIME
Demail.SetExtendedProperty(new ExtendedPropertyDefinition(3590, MapiPropertyType.SystemTime), historicalDate);
if (isread == false)
{
Demail.IsRead = isread;
}
if (_source.RequestedServerVersion == flagVersion && _destination.RequestedServerVersion == flagVersion)
{
Demail.Flag = _GetEmail.Flag;
}
_lstdestmail.Add(Demail);
_objtask = new TaskStatu();
_objtask.TaskId = _taskid;
_objtask.SubTaskId = subtaskid;
_objtask.FolderId = Convert.ToInt64(folderId);
_objtask.SourceItemId = Convert.ToString(_GetEmail.InternetMessageId.ToString());
_objtask.DestinationEmail = Convert.ToString(_fromEmail);
_objtask.CreatedOn = DateTime.UtcNow;
_objtask.IsSubFolder = false;
_objtask.FolderName = fold;
_objdbcontext.TaskStatus.Add(_objtask);
try
{
if (counter == countGroup)
{
Demails = new EmailMessage(_destination);
Demails.Service.CreateItems(_lstdestmail, _destinationFolder.Id, MessageDisposition.SaveOnly, SendInvitationsMode.SendToNone);
_objdbcontext.SaveChanges();
counter = 0;
_lstdestmail.Clear();
}
}
catch (Exception ex)
{
ClouldErrorLog.CreateError(_taskid, subtaskid, ex.Message + GetLineNumber(ex, _taskid, subtaskid), CreateInnerException(sub, fold, historicalDate));
counter = 0;
_lstdestmail.Clear();
continue;
}
This error occurs only if try to export in office 365 accounts and works fine in case of outlook 2010, 2013, 2016 etc..
Usually this is the case when exceed the EWS throttling in Exchange. It is explain in here.
Make sure you already knew throttling policies and your code comply with them.
You can find throttling policies using Get-ThrottlingPolicy if you have the server.
One way to solve the throttling issue you are experiencing is to implement paging instead of requesting all items in one go. You can refer to this link.
For instance:
using Microsoft.Exchange.WebServices.Data;
static void PageSearchItems(ExchangeService service, WellKnownFolderName folder)
{
int pageSize = 5;
int offset = 0;
// Request one more item than your actual pageSize.
// This will be used to detect a change to the result
// set while paging.
ItemView view = new ItemView(pageSize + 1, offset);
view.PropertySet = new PropertySet(ItemSchema.Subject);
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending);
view.Traversal = ItemTraversal.Shallow;
bool moreItems = true;
ItemId anchorId = null;
while (moreItems)
{
try
{
FindItemsResults<Item> results = service.FindItems(folder, view);
moreItems = results.MoreAvailable;
if (moreItems && anchorId != null)
{
// Check the first result to make sure it matches
// the last result (anchor) from the previous page.
// If it doesn't, that means that something was added
// or deleted since you started the search.
if (results.Items.First<Item>().Id != anchorId)
{
Console.WriteLine("The collection has changed while paging. Some results may be missed.");
}
}
if (moreItems)
view.Offset += pageSize;
anchorId = results.Items.Last<Item>().Id;
// Because you’re including an additional item on the end of your results
// as an anchor, you don't want to display it.
// Set the number to loop as the smaller value between
// the number of items in the collection and the page size.
int displayCount = results.Items.Count > pageSize ? pageSize : results.Items.Count;
for (int i = 0; i < displayCount; i++)
{
Item item = results.Items[i];
Console.WriteLine("Subject: {0}", item.Subject);
Console.WriteLine("Id: {0}\n", item.Id.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine("Exception while paging results: {0}", ex.Message);
}
}
}

How should I be using the Kentico TreeNode.Update method?

I am trying to run the attached code to update some data for a particular document type but it is not actually updating anything.
My currentDocumentNodeId() method is pulling back a NodeId based on some other criteria and then each of these Nodes that it is getting is of the type HG.DocumentLibraryItem which have the columns IsPublic, IsRepMining, IsRepPower, IsRepProcess, and IsRepFlexStream. But when I call the update method and then pull back those Columns in the SQL table for this Custom Document Type, the values are all Null. Each of those columns in the HG.DocumentLibraryItem document type are set to boolean I have tried using the Node.SetValue() method and setting it to true and 1; neither way works to update that column.
Any ideas what I am doing wrong? Am I doing the call correctly?
See my code below:
public static void GetDocumentAreaAssignments()
{
var cmd = new SqlCommand
{
CommandText ="This is pulling back 2 rows, one with Id and one with Text",
CommandType = CommandType.Text,
Connection = OldDbConnection
};
OldDbConnection.Open();
try
{
using (SqlDataReader rdr = cmd.ExecuteReader())
{
var count = 0;
while (rdr.Read())
{
try
{
var documentId = TryGetValue(rdr, 0, 0);
var areaAssignment = TryGetValue(rdr, 1, "");
var currentDocumentNodeId = GetNodeIdForOldDocumentId(documentId);
var node = currentDocumentNodeId == 0
? null
: Provider.SelectSingleNode(currentDocumentNodeId);
if (node != null)
{
switch (areaAssignment.ToLower())
{
case "rep mining":
node.SetValue("IsRepMining", 1);
break;
case "rep power":
node.SetValue("IsRepPower", 1);
break;
case "rep process":
node.SetValue("IsRepProcess", 1);
break;
case "rep flexStream":
node.SetValue("IsFlexStream", 1);
break;
case "public":
node.SetValue("IsPublic", 1);
break;
}
node.Update();
Console.WriteLine("Changed Areas for Node {0}; item {1} complete", node.NodeID,
count + 1);
}
}
catch (Exception ex)
{
}
count++;
}
}
}
catch (Exception)
{
}
OldDbConnection.Close();
}
The coupled data (as IsRepMining field) are only updated when you retrieve a node that contains them. To do that you have to use overload of the SelectSingleNode() method with a className parameter. However I'd recommend you to always use the DocumentHelper to retrieve documents. (It will ensure you work with the latest version of a document...in case of workflows etc.)
TreeProviderInstance.SelectSingleNode(1, "en-US", "HG.DocumentLibraryItem")
DocumentHelper.GetDocument(...)
DocumentHelper.GetDocuments(...)

Resources