EWS Exchange Web service API AutodiscoverUrl exception - c#

I get an error when I try to create an appointment:
The expected XML node type was XmlDeclaration, but the actual type is
Element.
This Exception occurs when I call AutodiscoverUrl.
I created a web service to do this.
[webMethod]
CreateAppointment()
{
var service = new ExchangeService(ExchangeVersion.Exchange2007_SP1)
{
Credentials = new WebCredentials("myAcount#gmail.com", "mypassowrd")
};
service.AutodiscoverUrl("myAcount#gmail.com");
//----------------------------------------------------------------------
var app = new Appointment(service)
{
Subject = "Meet George",
Body = "You need to meet George",
Location = "1st Floor Boardroom",
Start = DateTime.Now.AddHours(2),
End = DateTime.Now.AddHours(3),
IsReminderSet = true,
ReminderMinutesBeforeStart = 15
};
app.RequiredAttendees.Add(new Attendee("any#gmail.com"));
app.Save(SendInvitationsMode.SendToAllAndSaveCopy);
}

Some potential answers.
Passing in the wrong url or domain.
Passing in a bad email address.
Rebuilding the Windows Profile can sometimes help. (Warning: have an IT Admin do this). And it might be overkill.
A user could have an old, bad, or multiple outlook profiles set up. The email server name could be bad in the outlook profile. (See Control Panel > Mail)

Autodiscover depends on two things:
DNS entries that point from the users mail domain to the Autodiscover data on the Exchange server. Typically you would have a DNS entry with the name autodiscover.domain.com, but there's more than one way of setting this up for different versions of Exchange. If the correct DNS entry doesn't exist, auto-discovery will fail.
Autodiscover data hosted on the Exchange server (I believe it's an XML file) and accessed over HTTP. If this isn't accessible (perhaps it's behind a firewall) then auto-discovery will fail.
Check the appropriate DNS entries and autodiscover information is accessible to your client.

Related

SOAP error when connecting to NetSuite web services: "Namespace prefix ' soapenv' not defined"

I am getting the following error when connecting to a NetSuite production account, through the Suitetalk API:
I don't have problems connecting to the Sandbox account for this client. I am connecting through a C# WCF project. I don't believe the problem is with the c# project, since this code is being used in Production with many other clients.
It seems to me like the SOAP message being returned is incorrectly formatted - there seems to be a line break before the 'soapenv' element in the SOAP message. I am getting this error when creating a "get" request against the API(using passport login). This error occurs on any API call though, I did try simply logging in through the API as well.
I have double checked the login details and account information for this client and everything seems in orders. Besides, if this information is incorrect, I should be getting authentication errors - not malformed SOAP messages.
Any help will be appreciated, thanks!
It turns out that I needed to use the webservices.na3.netsuite WSDL. I was under the impression that the regular "webservices.netsuite" WSDL would direct any requests to the correct server.
So when connecting to a NetSuite account through SuiteTalk, be sure to make use of the correct WSDL and specify the correct endpoint along with your login credentials. You can check which server your account is hosted on by looking at the URL when logged into your NetSuite account.
Update
I made use of the newest 'DataCenterAwareNetSuiteService' class to dynamically get the correct data center for the current account that I am trying to connect to:
class DataCenterAwareNetSuiteService : NetSuiteService
{
private System.Uri OriginalUri;
public DataCenterAwareNetSuiteService(string account, bool doNotSetUrl)
: base()
{
OriginalUri = new System.Uri(this.Url);
if (account == null || account.Length == 0)
account = "empty";
if (!doNotSetUrl)
{
//var temp = getDataCenterUrls(account);
DataCenterUrls urls = getDataCenterUrls(account).dataCenterUrls;
Uri dataCenterUri = new Uri(urls.webservicesDomain + OriginalUri.PathAndQuery);
this.Url = dataCenterUri.ToString();
}
}
public void SetAccount(string account)
{
if (account == null || account.Length == 0)
account = "empty";
this.Url = OriginalUri.AbsoluteUri;
DataCenterUrls urls = getDataCenterUrls(account).dataCenterUrls;
Uri dataCenterUri = new Uri(urls.webservicesDomain + OriginalUri.PathAndQuery);
this.Url = dataCenterUri.ToString();
}
}
The above is called like so:
new DataCenterAwareNetSuiteService("*account number*", false);
With the latest version of NetSuite, some changes have been made to URLs. For instance, now you can have more than one SandBox URL. Because of this, the URL format has changed. The account number used when authenticating is also now different. For sandboxes the account Id is now passed up as ACCOUNTNUMBER_SANDBOXID, for example 12345678_SB1.
You can determine the URLs for the SOAP and REST services by using the datacenterurls endpoint and supplying the account # you would like to determine the URLS for.
https://rest.netsuite.com/rest/datacenterurls?account=YOUR_ACCOUNT_NUMBER
The functionality below is based on the answer from #Charl above.
I have made a couple changes below that provides the same functionality without using inheritance.
This may be a simpler implementation for a newer programmer who does not know how to use an inherited class.
var accountId = "1234567"; // Insert your account ID here
var Service = new NetSuiteService();
Service.Url = new Uri(Service.getDataCenterUrls(accountId).dataCenterUrls.webservicesDomain + new Uri(Service.Url).PathAndQuery).ToString();

LDAP search fails on server, not in Visual Studio

I'm creating a service to search for users in LDAP. This should be fairly straightforward and probably done a thousand times, but I cannot seem to break through properly. I thought I had it, but then I deployed this to IIS and it all fell apart.
The following is setup as environment variables:
ldapController
ldapPort
adminUsername 🡒 Definitely a different user than the error reports
adminPassword
baseDn
And read in through my Startup.Configure method.
EDIT I know they are available to IIS, because I returned them in a REST endpoint.
This is my code:
// Connect to LDAP
LdapConnection conn = new LdapConnection();
conn.Connect(ldapController, ldapPort);
conn.Bind(adminUsername, adminPassword);
// Run search
LdapSearchResults lsc = conn.Search(
baseDn,
LdapConnection.SCOPE_SUB,
lFilter,
new string[] { /* lots of attributes to fetch */ },
false
);
// List out entries
var entries = new List<UserDto>();
while (lsc.hasMore() && entries.Count < 10) {
LdapEntry ent = lsc.next(); // <--- THIS FAILS!
// ...
}
return entries;
As I said, when debugging this in visual studio, it all works fine. When deployed to IIS, the error is;
Login failed for user 'DOMAIN\IIS_SERVER$'
Why? The user specified in adminUsername should be the user used to login (through conn.Bind(adminUsername, adminPassword);), right? So why does it explode stating that the IIS user is the one doing the login?
EDIT I'm using Novell.Directory.Ldap.NETStandard
EDIT The 'user' specified in the error above, is actually NOT a user at all. It is the AD registered name of the computer running IIS... If that makes any difference at all.
UPDATE After consulting with colleagues, I set up a new application pool on IIS, and tried to run the application as a specified user instead of the default passthrough. Exactly the same error message regardless of which user I set.
Try going via Network credentials that allows you to specify domain:
var networkCredential = new NetworkCredential(userName, password, domain);
conn.Bind(networkCredential);
If that does not work, specify auth type basic (not sure that the default is) before the call to bind.
conn.AuthType = AuthType.Basic;

Exchange Web Services Autodiscover non default link

I am writing a piece of software that runs on a utility device on a customers network, but not on the domain. The autodiscover service is not available off domain the same as it is either on the domain or even on the internet. None of the ways the service works by default will find it according to the docs, but the customer's IT staff tells me, supposedly :/ , it will all work if I can access Autodiscover at the link they gave me. Is there any way to override the default approach and pass it this url to autodiscover from? Hardcoding the link to /exchange.asmx is not an option nor is adding this device to the domain.
I am reusing, and now tweaking, a tried and true piece of software that has been deployed many times, but this situation is a first.
Using the EWS Managed API you may be able to do it using the AutodiscoverService class. It has a constructor that takes the URI of the Autodiscover service as a parameter.
Your code should look something like this. Note that I disable SCP lookup as you are not on a domain. I have not actually tried this code but give it a try:
AutodiscoverService ads = new AutodiscoverService(new Uri("..."));
ads.EnableScpLookup = false;
ads.Credentials = new NetworkCredential(...);
ads.RedirectionUrlValidationCallback = delegate { return true; };
GetUserSettingsResponse grResp = ads.GetUserSettings("someemail#domain.com", UserSettingName.ExternalEwsUrl);
Uri casURI = new Uri(grResp.Settings[UserSettingName.ExternalEwsUrl].ToString());
var service = new ExchangeService()
{
Url = casURI,
Credentials = ads.Credentials,
};

AppFabric - putting fine, getting times out?

After painfully trying to get my virtual environment up and running with Appfabric Caching (1.1), I am able to run 2 nodes into 1 cache cluster.
Both show system up which is good. Before, it was not and was a pain.
So I am now creating a demo app.
The app is being developed on the host computer which can connect to the virtual environment (using VMware and they are all in a domain except the host).
I can put things in the cache and I can see the cache statistics which reflects what I have put in the cache.
But when getting - it fails! It just times out and no idea why or where to go:
? u.Email
"36277#bloggs.com"
? CacheManager.Instance.Cache.GetCacheItem(u.Email)
'CacheManager.Instance.Cache.GetCacheItem(u.Email)' threw an exception of type 'Microsoft.ApplicationServer.Caching.DataCacheException'
base {System.Exception}: {"ErrorCode<ERRCA0018>:SubStatus<ES0001>:The request timed out.. Additional Information : The client was trying to communicate with the server : net.tcp://AppFabricTwo.appfabric.demo.com:22233"}
ErrorCode: 18
HelpLink: "http://go.microsoft.com/fwlink/?LinkId=164049"
Message: "ErrorCode<ERRCA0018>:SubStatus<ES0001>:The request timed out.. Additional Information : The client was trying to communicate with the server : net.tcp://AppFabricTwo.appfabric.demo.com:22233"
SubStatus: -1
TrackingId: {00000000-0000-0000-0000-000000000000}
I have AppFabricOne and AppFabricTwo. I can communicate between them no problems and I can ping and access these 2 from the HOST computer itself (which is hosting the VM's)
Any ideas why this would be and what to do? Windows firewalls on the VM computers are all disabled and these are joined to a domain (And using SQL).
My code:
Adding:
Random r = new Random();
int idChosen = r.Next(1, 99999);
User u = new User { LastName = "Bloggs", FirstName = "Joe", CellPhone = "(555) 555-5555", DOB = DateTime.Today.AddYears(-30), UserID = idChosen, Email = idChosen.ToString() + "#bloggs.com" };
DataCacheItemVersion item = CacheManager.Instance.Cache.Put(u.Email, u, this.txtRegion.Text);
Retrieving:
CacheManager.Instance.Cache.GetCacheItem(u.Email)
yes, I have also tried GetRegionItem but that still gives me the same error as GetCacheItem.
Are you using the same DataCacheFactory object for getting the cache items as the one you are using to put items in the cache ? The fact that PUT works and GET doesn't makes me think that they are different datacachefactory objects somehow.
also are you able to ping to FQDN AppFabricTwo.appfabric.demo from your client machine and is it resolving to correct IP address I.e. Same as appfabrictwo ? Also check telnet to port 22233 is working from your client (if put works this should work anyways though

Exchange Server Login Credentials Setup

I just want to pass this by you and make sure that I am doing this right. My code:
ExchangeService _mailService = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
_mailService.Credentials = new System.Net.NetworkCredential(#"userName", #"password", #"mydomainInfo");
//_mailService.UseDefaultCredentials = true;
_mailService.Url = new Uri("https://webmail.mydomain.com/ews/exchange.asmx");
try
{
ItemView allItems = new ItemView(100);
SearchFilter searchFilterInbox = new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false);
Folder _inbox = Folder.Bind(_mailService, WellKnownFolderName.Inbox);
// <SNIP>
So I get this far and the Bind returns an Authentication Fail (401). If I comment out the '.Credentials' and uncomment '.UseDefaultCredentials', I log in just fine. But I need to access a different inbox folder. I pulled the UserName and Domain Name from my account on Outlook. Even if I use my own login information, I still get this error. To me that says I'm just not providing the right information. Thoughts? I can log into the web side of the service just fine.
Well I solved my own problem. It was what I was suspecting. I just didn't have the correct data in the "domain" and "username" fields. I was actually calling the server the Exchange Server was on. So I changed it to the domain that my computer is logged into and changed the user id from "me#email.com" to "me" and it works! So I had it all setup right, just wrong information.

Categories