I have a webdav function listed below:
The behavior is completely unexpected....
When I first run the function and pass a URL to a resource (folder in sharepoint) that does not exist, I get a 404 which is expected. I then use another function to create the resource using THE SAME credentials as in this method. No problems yet...
However on 2nd run, after the resource has been created - when I check if resource exists, now I get a 401.
Whats important to note here is that the same credentials are used to check for 401 and create folder, so clearly the credentials are fine...
So it must be something else.... All I want to do is check if a resource exists in SharePoint.... any ideas how to improve this function? Or any theory as to why its giving this 401...
private bool MossResourceExists(string url)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "HEAD";
// Create a new CredentialCache object and fill it with the network
// credentials required to access the server.
var myCredentialCache = new CredentialCache();
if (!string.IsNullOrEmpty(this.Domain ))
{
myCredentialCache.Add(new Uri(url),
"NTLM",
new NetworkCredential(this.Username , this.Password , this.Domain )
);
}
else
{
myCredentialCache.Add(new Uri(url),
"NTLM",
new NetworkCredential(this.Username , this.Password )
);
}
request.Credentials = myCredentialCache;
try
{
request.GetResponse();
return true;
}
catch (WebException ex)
{
var errorResponse = ex.Response as HttpWebResponse;
if (errorResponse != null)
if (errorResponse.StatusCode == HttpStatusCode.NotFound)
{
return false;
}
else
{
throw new Exception("Error checking if URL exists:" + url + ";Status Code:" + errorResponse.StatusCode + ";Error Message:" + ex.Message ) ;
}
}
return true;
}
The only clue I have is that when using http://mysite.com/mydoclib/mytoplevelfolder it works.... any sub folders automatically give 401's....
The thing is that you can't pass the whole url that includes folders to the CredentialCache.Add() method.
For example:
http://MyHost/DocumentLibrary/folder1/folder2 will not work as an Uri to the Add() method, but
http://MyHost/DocumentLibrary/ will work.
I would guess that the lack of permissioning capabilities on folder level in SharePoint is the reason for this. Or the way that otherwise SharePoint handles folders.
What you can do is to separate the parameters in your method to accept a base url (including document libraries / lists) and a folder name parameter.
The CredentialCache gets the base url and the request object gets the full url.
Another way is to use the
request.Credentials = System.Net.CredentialCache.DefaultCredentials;
credentials instead. And, if necessary, do an impersonation if you want to use another account than the executing one.
A third variation is to try with authentication type set to Kerberos instead of NTLM.
Here is my test code. I am able to reproduce the problem if I replace the problem with your code, and this code works for me.
static void Main(string[] args)
{
bool result = MossResourceExists("http://intranet/subtest/content_documents/", "testfolder/testfolder2");
}
private static bool MossResourceExists(string baseUrl, string folder)
{
string completeUrl = baseUrl + folder;
var request = (HttpWebRequest)WebRequest.Create(completeUrl);
request.Method = "HEAD";
// Create a new CredentialCache object and fill it with the network
// credentials required to access the server.
var myCredentialCache = new CredentialCache();
if (!string.IsNullOrEmpty(Domain))
{
myCredentialCache.Add(new Uri(baseUrl),
"NTLM",
new NetworkCredential(Username, Password, Domain)
);
}
else
{
myCredentialCache.Add(new Uri(baseUrl),
"NTLM",
new NetworkCredential(Username, Password)
);
}
request.Credentials = myCredentialCache;
//request.Credentials = System.Net.CredentialCache.DefaultCredentials;
try
{
WebResponse response = request.GetResponse();
return true;
}
catch (WebException ex)
{
var errorResponse = ex.Response as HttpWebResponse;
if (errorResponse != null)
if (errorResponse.StatusCode == HttpStatusCode.NotFound)
{
return false;
}
else
{
throw new Exception("Error checking if URL exists:" + completeUrl + ";Status Code:" + errorResponse.StatusCode + ";Error Message:" + ex.Message);
}
}
return true;
}
Hope this helps.
Related
I'm using RequestJWTUserToken (docusign.esign.dll file version 4.1.1.0) to generate access tokens for a web application for each user, however occasionally the web application is sending documents from the wrong User's account.
I have logged the steps of the application, and when the error occurs, 2 (or more) of the my users are authenticating their UserIDs through our Integrator key at about the exact same time.
Each user is re-authenticating each time it is time to send a document. The logs that I'm writing show that I am sending in the correct GUID in the parameter list to the RequestJWTUserToken method. Any ideas on what could be occurring?
The method snippet is:
private OAuth.OAuthToken UpdateToken(string strUserGuid)
{
try
{
string ServicePointManager_SecurityProtocol_TLS_12 = ConfigurationManager.AppSettings["ServicePointManager_SecurityProtocol_TLS_12"];
System.Collections.Specialized.NameValueCollection obj = ConfigurationManager.AppSettings;
if (ServicePointManager_SecurityProtocol_TLS_12 == null || ServicePointManager_SecurityProtocol_TLS_12.Equals("true", StringComparison.OrdinalIgnoreCase)) ServicePointManager.SecurityProtocol = Tls12;
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
var mtype = ServicePointManager.SecurityProtocol;
OAuth.OAuthToken authToken =
ApiClient.RequestJWTUserToken(IntegratorKey,
strUserGuid,
AuthServer,
PrivateKey,
1);
AccessToken = authToken.access_token;
//set Account Property
if (Account == null) Account = GetAccountInfo();
ApiClient = new ApiClient(Account.BaseUri + "/restapi");
ExpiresIn = DateTime.Now.Second + authToken.expires_in.Value;
return authToken;
}
catch (ApiException ex)
{
if (ex.Source.Contains("DocuSign.eSign") && strUserGuid != "")
{
if (ex.Message.Contains("consent_required")) //send email with consent to sign link
throw new Exception("DocuSign Consent Required for " + HttpContext.Current.Session["USER_FULLNAME"]);
else
switch (ex.ErrorCode)
{
case 400: throw new Exception("Bad Request: The requested UserID may exist in DocuSign, but there is an issue with the Docusign User Account.");
default: throw new Exception("General Error");
}
}
else throw;
}
catch
{
throw;
}
}
Having the following URL
https://test.sharepoint.com/shared%20documents/MyFolder1/myImg1.jpeg
I need to send a request for parent URL of this item (in this specific case image) and to get a response:
https://test.sharepoint.com/shared%20documents/MyFolder1/
Does such a request exists if using a CSOM or Office 365 Activity API?
Where in documentation can i find such examples?
static public string ReturnFileParentUrl(string url)
{
try
{
Uri uri = new Uri("https://XXX.sharepoint.com/");
using (var ctx = GetContext(uri, "YYY#DOMAIN.com", "password"))
{
Microsoft.SharePoint.Client.File item = ctx.Web.GetFileByServerRelativeUrl(url);
ctx.Load(item);
ctx.ExecuteQuery();
Console.WriteLine("file: {0}\n", item.Name);
Console.WriteLine("Type: {0}\n", item.TypedObject.ToString());
if (item.TypedObject.ToString() == "Microsoft.SharePoint.Client.File") //To check if there is a better way to check if the item is a file
if (item.ServerObjectIsNull != true)
{
ctx.Load(item, i => i.ListItemAllFields);
ctx.ExecuteQuery();
var folder = ctx.Web.GetFolderByServerRelativeUrl((string)item.ListItemAllFields["FileDirRef"]);
ctx.Load(folder);
ctx.ExecuteQuery();
Console.WriteLine("parent relative url {0}\n", folder.ServerRelativeUrl);
return folder.ServerRelativeUrl;
}
return null;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}
What is the best way to tell if an OrganizationServiceProxy has successfully connected to CRM?
I am using GetEnumerator() on AccountSet as this fails if not connected.
/* Tries to connect to CRM and return false if failure - credentials arguments */
public bool Connect(string username, string password, string uri)
{
try
{
var cred = new ClientCredentials();
cred.UserName.UserName = username;
cred.UserName.Password = password;
service = new OrganizationServiceProxy(new Uri(uri), null, cred, null);
service.EnableProxyTypes(); // Allow LINQ early bound queries
linq = new Context(service);
/* This is where I need help */
var e = linq.AccountSet.GetEnumerator(); // this fails if not connected
}
catch
{
return false;
}
return true;
}
Service and Linq are private fields.
Context is the serviceContextName in crmsvcutil.exe.
I am in the habit of using the name "linq" for the Context object.
There must be a better way.
The simplest way is to execute a WhoAmIRequest, this because when you connect to CRM you need to provide valid credentials.
If the credentials are correct the WhoAmIRequest will return the current user GUID, if are not correct the request will fail.
So your code can be:
public bool Connect(string username, string password, string uri)
{
try
{
var cred = new ClientCredentials();
cred.UserName.UserName = username;
cred.UserName.Password = password;
service = new OrganizationServiceProxy(new Uri(uri), null, cred, null);
WhoAmIRequest request = new WhoAmIRequest();
WhoAmIResponse response = (WhoAmIResponse)service.Execute(request);
Guid userId = response.UserId;
}
catch
{
return false;
}
return true;
}
I have this code to change the password of a user in an active directory:
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://0.0.0.0/CN=John Smith,OU=12345,OU=Project,DC=mysite,DC=local");
directoryEntry.AuthenticationType = AuthenticationTypes.Secure;
directoryEntry.Username = "adminusername";
directoryEntry.Password = "adminpassword";
directoryEntry.Invoke("SetPassword", new object[] { "newPassword" });
directoryEntry.Properties["LockOutTime"].Value = 0; //unlock account
When I try to execute this code directly into the server where is located the active directly, this work perfectly but when I try to execute it with a machine located in another domain, I receive this error:
System.Reflection.TargetInvocationException: Exception has been thrown by the ta
rget of an invocation. ---> System.Runtime.InteropServices.COMException: The RPC
server is unavailable. (Exception from HRESULT: 0x800706BA)
This is the only one limitation that I have because with the same admin user and other credentials, I'm able to add user, remove user, add group, rename any object, etc... BUT not changing password.
Not that I tried with this code and it doesn't work too:
public bool SetPassword(string userName, string newPassword, Domain.ActiveDirectory.Credentials credentials)
{
try
{
using (var pc = new PrincipalContext(ContextType.Domain, credentials.ServerName, credentials.OrganizationalUnitsDn + "," + credentials.DomainControllerName))
{
using (var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, userName))
{
if (user == null)
{
return false;
}
user.SetPassword(newPassword);
return true;
}
}
}
catch (Exception e)
{
return false;
}
}
Anyone have an idea?
Thank you.
This is for a internal portal , and I am looking for a widget that allows user to login to their gmail account and view their account. I tried the Google gadget but it shows the following error
"this is a builtin module, so the UserPrefs and Content are ignored."
also since gadgets are gonna be discontinued I am uncomfortable using that as a long term solution.
Even widget from widgetbox, netvibes etc. don't seem to be working.
Is it because there has been some policy change by Google preventing these widgets from working ? or am i doing something wrong.
I also tried to use the Google widgets in a my site, but unfortunalitly it doesn't work.
It gives the Content are ignored.
No widgets haven't work for my code.
I think there is a policy change in it. But i didn't have any clew about it.
When you say 'login to their account' and what you want to do. You can use OAuth where a user grants your application permission to access their account.
Google have their own library written in a number of languages - some examples using Java, Python and PHP can be found here: https://developers.google.com/google-apps/gmail/xoauth2_libraries
When you use OAuth you register with Google and they give you a ConsumerKey and ConsumerSecret - this is what identifies you application to Google.
Once you do that provide a link to allow them to login - this will take them to a Google login, they login with their account - then they grant permission.
I've had problems using OAuth with GMail but successfully managed it with say their Contacts. For example this is the code I am using to retrieve all a users contacts
public List<Person> GetContacts()
{
OAuthParameters parameters = null;
GOAuthRequestFactory requestFactory = null;
ContactsService service = null;
ContactsQuery feedQuery = null;
ContactsFeed feed = null;
List<Person> contacts = null;
try
{
if (ConsumerKey == String.Empty) throw new ValueIsEmptyOrNullException("ConsumerKey");
if (ConsumerSecret == String.Empty) throw new ValueIsEmptyOrNullException("ConsumerSecret");
if (OAuthCallback == String.Empty) throw new ValueIsEmptyOrNullException("OAuthCallback");
if (SignatureMethod == String.Empty) throw new ValueIsEmptyOrNullException("SignatureMethod");
if (ApplicationName == String.Empty) throw new ValueIsEmptyOrNullException("ApplicationName");
if (Token == String.Empty) throw new ValueIsEmptyOrNullException("Token");
if (Nonce == String.Empty) throw new ValueIsEmptyOrNullException("Nonce");
if (Verifier == String.Empty) throw new ValueIsEmptyOrNullException("Verifier");
if (Scope == String.Empty)
Scope = "https://www.google.com/m8/feeds";
parameters = new OAuthParameters();
parameters.ConsumerKey = ConsumerKey;
parameters.ConsumerSecret = ConsumerSecret;
parameters.Scope = Scope;
parameters.Callback = OAuthCallback;
parameters.SignatureMethod = SignatureMethod;
parameters.Timestamp = Toolbox.GenerateTimeStamp();
parameters.Token = Token;
parameters.TokenSecret = TokenSecret;
parameters.Nonce = Nonce;
parameters.Verifier = Verifier;
requestFactory = new GOAuthRequestFactory("c1", ApplicationName, parameters);
service = new ContactsService(ApplicationName);
service.RequestFactory = requestFactory;
feedQuery = new ContactsQuery(ContactsQuery.CreateContactsUri("default"));
feed = service.Query(feedQuery);
if (feed.Entries.Count > 0)
{
contacts = new List<Person>();
foreach (ContactEntry contact in feed.Entries)
{
try
{
if (contact.Name != null)
{
Person person = new Person();
int idStart = contact.Id.Uri.ToString().LastIndexOf('/');
if (idStart > 0)
{
person.PersonId = contact.Id.Uri.ToString().Substring(contact.Id.Uri.ToString().LastIndexOf('/') + 1);
}
else
{
person.PersonId = contact.Id.Uri.ToString();
}
person.GivenName = contact.Name.GivenName;
person.Surname = contact.Name.FamilyName;
person.Birthday = contact.Birthday;
person.Initials = contact.Initials;
person.Location = contact.Location;
person.MaidenName = contact.MaidenName;
person.Occupation = contact.Occupation;
person.Photograph = contact.PhotoUri.ToString();
person.Surname = contact.Name.FamilyName;
if (contact.Emails.Count > 0)
person.Email = contact.Emails[0].Address;
contacts.Add(person);
}
}
catch (System.Exception ex)
{
throw ex;
}
finally
{
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return contacts;
}