Application to sharepoint URL - share authentication sessions - c#

I am currently using the SharePoint Authentication.asmx to create an authentication session from within my C# application. This is all working as expected and I can upload files etc
I also have links to my sharepoint site within my application using:
Process.Start("**/documents/Forms/***"); //URL modified for StackOverflow
The issue I have is that my users are prompted to login from the browser when clicking on a button with my application, which is understandable since the browser doesn't have a session. Is there some way I can share the session I have in my app with the browser?
This is the code I am using to authenticate:
using (SPAuth.Authentication authSvc = new SPAuth.Authentication())
{
authSvc.Url = #"***/_vti_bin/Authentication.asmx"; //URL modified for StackOverflow
authSvc.CookieContainer = new System.Net.CookieContainer();
//set the FBA login information
SPAuth.LoginResult result = authSvc.Login(username, password);
if (result.ErrorCode == SPAuth.LoginErrorCode.NoError)
{
try
{
...
}
catch
{
...
}
}
}

if you can maintain browser object following method might solve your problem.
public void AuthenticateInSharePoint(String url, String login, String password)
{
try
{
var uri = new Uri(url);
var uriBuilder = new UriBuilder();
uriBuilder.Scheme = uri.Scheme;
uriBuilder.Port = uri.Port;
uriBuilder.Host = uri.Host;
uriBuilder.Path = "_forms/default.aspx";
uriBuilder.Query = String.Format("ReturnUrl={0}", HttpUtility.UrlEncode(uri.LocalPath));
var request = (HttpWebRequest)HttpWebRequest.Create(uriBuilder.ToString());
request.ContentType = "application/x-www-form-urlencoded";
request.AllowAutoRedirect = true;
var response = (HttpWebResponse)request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
var html = reader.ReadToEnd();
var doc = new HtmlDocument();
doc.LoadHtml(html);
foreach (var node in doc.DocumentNode.Descendants("script").ToList())
node.Remove();
foreach (var node in doc.DocumentNode.Descendants("link").ToList())
node.Remove();
var form = doc.DocumentNode.Descendants("form").FirstOrDefault();
if (form != null)
{
form.Attributes["action"].Value = uriBuilder.ToString();
var script = doc.CreateElement("script");
script.InnerHtml = String.Format(#"
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', 'ctl00$PlaceHolderMain$signInControl$login');
input.value = 'Sign In';
document.forms[0].appendChild(input);
document.getElementById('ctl00_PlaceHolderMain_signInControl_UserName').value=""{0}"";
document.getElementById('ctl00_PlaceHolderMain_signInControl_password').value=""{1}"";
document.forms[0].submit();", login, password);
var body = doc.DocumentNode.Descendants("body").FirstOrDefault();
if (body != null)
body.AppendChild(script);
}
var builder = new StringBuilder();
using (var writer = new StringWriter(builder))
doc.Save(writer);
return Content(builder.ToString(), response.ContentType);
}
}
catch (Exception e)
{
Log.Error(e, "Failed to authenticate user in SharePoint.");
}
}

Related

I want to implement sharepoint document search using C# api

I want to search sharepoint document using C# api call.
I am trying below code:
string URL = "http://server/_api/search/query?query_parameter=value&query_parameter=value";
System.Net.Http.HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "XXXXX", "XXXXXX"))));
using (client)
{
HttpResponseMessage httpResponseMessage = await client.GetAsync(URL);
HttpResponseMessage responsemMsgx = httpResponseMessage;
if (responsemMsgx.IsSuccessStatusCode)
{
}
}
But,i am have a doubt regarding URL below:
string URL = "http://server/_api/search/query?query_parameter=value&query_parameter=value";
Please help me with the sharepoint server and constructing the URL.
My expected output is something like JSON .
If you want to search documents, we can use the Search REST API below to achieve it.
/_api/search/query?querytext='IsDocument:True'
C# example:
string siteUrl = "http://sp2013/sites/team";
string searchQuery = "/_api/search/query?querytext='IsDocument:True'";//search all documents
var credential = new System.Net.NetworkCredential("username", "password", "domainname");
HttpClientHandler handler = new HttpClientHandler() { Credentials = credential };
HttpClient client = new HttpClient(handler);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
client.DefaultRequestHeaders.Add("ContentType", "application/json;odata=verbose");
var result = client.GetAsync(siteUrl+searchQuery).Result;
var content = result.Content.ReadAsStringAsync().Result;
JObject jobj = JObject.Parse(content);
JArray jarr = (JArray)jobj["d"]["query"]["PrimaryQueryResult"]["RelevantResults"]["Table"]["Rows"]["results"];
foreach (JObject j in jarr)
{
JArray results = (JArray)j["Cells"]["results"];
var title = "";
var path = "";
foreach (JObject r in results)
{
if (r["Key"] != null)
{
if (r["Key"].ToString() == "Title")
{
title = r["Value"].ToString();
}
if (r["Key"].ToString() == "Path")
{
path = r["Value"].ToString();
}
}
}
Console.WriteLine(title + "|" + path);
}

Authenticate SharePoint online REST API without user name and password

I am trying to build a console app that reads the data from SharePoint list.
But i dont want to pass the user credentials in order to authenticate, instead use the token. Is this possible?
I tried using the following code but i get forbidden error while trying to GetFormDigest
static void Main(string[] args)
{
string sConnStr = "https://sab/sites/DevT";
Uri oUri = null;
oUri = new Uri(sConnStr + "/_api/web/lists/getbytitle('sd')/GetItems");
string sResult = string.Empty;
string stringData = "{'query' : {'__metadata': { 'type': 'SP.CamlQuery' }, 'ViewXml':'<View><Query><Where><Eq><FieldRef Name =\"Title\"/><Value Type=\"Text\">HR</Value></Eq></Where></Query></View>'}}";
HttpWebRequest oWebRequest = (HttpWebRequest)WebRequest.Create(oUri);
oWebRequest.Credentials = CredentialCache.DefaultNetworkCredentials;
oWebRequest.Method = "POST";
oWebRequest.Accept = "application/json;odata=verbose";
oWebRequest.ContentType = "application/json;odata=verbose";
oWebRequest.Headers.Add("X-RequestDigest", GetFormDigest());
oWebRequest.ContentLength = stringData.Length;
StreamWriter writer = new StreamWriter(oWebRequest.GetRequestStream());
writer.Write(stringData);
writer.Flush();
WebResponse wresp = oWebRequest.GetResponse();
using (StreamReader sr = new StreamReader(wresp.GetResponseStream()))
{
sResult = sr.ReadToEnd();
}
}
public static string GetFormDigest()
{
string sFormDigest = null;
string sConnStr = "https://sab/sites/DevT";
Uri oUri = null;
oUri = new Uri(sConnStr + "/_api/contextinfo");
HttpWebRequest oWebRequest = HttpWebRequest.Create(oUri) as HttpWebRequest;
oWebRequest.UseDefaultCredentials = true;
oWebRequest.Method = "POST";
oWebRequest.Accept = "application/json;odata=verbose";
oWebRequest.ContentLength = 0;
oWebRequest.ContentType = "application/json";
string sResult;
WebResponse sWebReponse = oWebRequest.GetResponse();
using (StreamReader sr = new StreamReader(sWebReponse.GetResponseStream()))
{
sResult = sr.ReadToEnd();
}
var jss = new JavaScriptSerializer();
var val = jss.Deserialize<Dictionary<string, object>>(sResult);
var d = val["d"] as Dictionary<string, object>;
var wi = d["GetContextWebInformation"] as Dictionary<string, object>;
sFormDigest = wi["FormDigestValue"].ToString();
return sFormDigest;
}
You could use Add-in authentication to access SharePoint data.
You could check my test demo below.
https://social.msdn.microsoft.com/Forums/office/en-US/d33f5818-f112-42fb-becf-3cf14ac5f940/app-only-token-issue-unauthorized-access?forum=appsforsharepoint

Download a file from sharepoint

I am trying to download a file from sharepoint, I have this code and throw error code 500.
static void DownloadFile(){
string serverFilePath = "Here goes my URL, that open the file from any tab";
var password = new SecureString();
foreach (char c in Configuration.password) {
password.AppendChar(c);
}
// theese are the credentials and work fine because I tested in another method
var o365credentials = new SharePointOnlineCredentials(Configuration.userName, password);
var url = string.Format("{0}/{1}", Configuration.siteUrl, serverFilePath);
// My destination folder
string destPath = #"C:\publisher";
var request = System.Net.HttpWebRequest.Create(url);
request.Credentials = o365credentials;
using (var sReader = new StreamReader(request.GetResponse().GetResponseStream())) {
using (var sWriter = new StreamWriter(destPath)) {
sWriter.Write(sReader.ReadToEnd());
}
}
}
you can achieve this task using WebRequest in order to download files from sharepoint site:
public void DownloadFile(string serverFilePath, string destPath)
{
var url = string.Format("{0}/{1}", ServerURL, serverFilePath);
Directory.CreateDirectory(Path.GetDirectoryName(destPath)); // this method creates your directory
var request = System.Net.HttpWebRequest.Create(url);
request.Credentials = System.Net.CredentialCache.DefaultCredentials;
using (var sReader = new StreamReader(request.GetResponse().GetResponseStream()))
{
using (var sWriter = new StreamWriter(destPath))
{
sWriter.Write(sReader.ReadToEnd());
}
}
}
if you wish to use the Client-object-model you read that:
How to get a file using SharePoint Client Object Model with only an absolute url at hand?
Edit: fixed the spelling of CreateDirectory call

Htmlagilitypack after login to Https Website with HttpWebRequest?

I want to parse some html site like pluralsight,Forexample (https://app.pluralsight.com/id?), So How can I first login site programmaticaly (without using webbrowser control) then call another url (for example : Pluralsight) and get response and parse with Htmlagility pack.
But I've written a login code, but I do not know the next step.
public class Login
{
private CookieContainer Cookies = new CookieContainer();
public void SiteLogin(string username, string password)
{
Uri site = new Uri("https://app.pluralsight.com/id?");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(site);
wr.Method = "Post";
wr.ContentType = "application/x-www-form-urlencoded";
wr.Referer = "https://app.pluralsight.com/id?";
wr.CookieContainer = Cookies;
var parameters = new Dictionary<string, string>{
{"realm", "vzw"},
{"goto",""},
{"gotoOnFail",""},
{"gx_charset", "UTF-8"},
{"rememberUserNameCheckBoxExists","Y"},
{"IDToken1", username},
{"IDToken2", password}
};
string input = string.Empty;
using (var requestStream = wr.GetRequestStream())
using (var writer = new StreamWriter(requestStream, Encoding.UTF8))
writer.Write(ParamsToFormEncoded(parameters));
using (var response = (HttpWebResponse)wr.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
//but I do not know the next step.
}
}
}
private string ParamsToFormEncoded(Dictionary<string, string> parameters)
{
return string.Join("&", parameters.Select(kvp => Uri.EscapeDataString(kvp.Key).Replace("%20", "+")
+ "=" + Uri.EscapeDataString(kvp.Value).Replace("20%", "+")
).ToArray());
}
}
You have to get the stream for the response via HttpWebResponse.GetResponseStream and then load the document via the Load method of the HtmlDocument.
var doc = new HtmlAgilityPack.HtmlDocument();
doc.Load(response.GetResponseStream());
//further processing...

Delete File in SharePoint folder using C#

I am using SharePoint ExcelService to manipulate an excel file and then save it to the Shared Documents folder using
ExcelService.SaveWorkbookCopy()
Now I want to delete those files I saved earlier. What is the best way to achieve this using C# in a Asp.Net MVC Application?
I tried it using the REST Service, but I could not really find any tutorials and as the code is now, I get a WebException "The remote server returned an error: (403) Forbidden."
I tried two versions for my REST URL, neither worked.
var fileSavePath = "http://sharepointserver/Collaboration/workrooms/MyWebSiteName/Shared%20Documents/";
var excelRestPath_1 = "http://sharepointserver/Collaboration/workrooms/MyWebSiteName/_api/web/";
var excelRestPath_2 = "http://sharepointserver/_api/web/";
public static bool DeleteExcelFromSharepoint(int id, string excelRestPath)
{
try
{
string filePath = "/Shared%20Documents/" + id + ".xlsm";
string url = excelRestPath + "GetFileByServerRelativeUrl('" + filePath + "')";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "DELETE";
request.Headers.Add(HttpRequestHeader.IfMatch, "*");
request.Headers.Add("X-HTTP-Method", "DELETE");
request.Credentials = System.Net.CredentialCache.DefaultCredentials;
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
{
throw new ApplicationException(String.Format("DELETE failed. Received HTTP {0}", response.StatusCode));
}
return true;
}
}
catch (Exception ex)
{
CustomLogger.Error("Error deleting Excel from Sharepoint", ex);
return false;
}
}
Use nuget package Microsoft.SharePointOnline.CSOM:
using (var sp = new ClientContext("webUrl"))
{
sp.Credentials = System.Net.CredentialCache.DefaultCredentials;
sp.Web.GetFileByServerRelativeUrl(filePath).DeleteObject();
sp.ExecuteQuery();
}
that will ensure that file is removed - if you want to make sure the file existed during removal:
using (var sp = new ClientContext("webUrl"))
{
sp.Credentials = System.Net.CredentialCache.DefaultCredentials;
var file = sp.Web.GetFileByServerRelativeUrl(filePath);
sp.Load(file, f => f.Exists);
file.DeleteObject();
sp.ExecuteQuery();
if (!file.Exists)
throw new System.IO.FileNotFoundException();
}
If you are using REST, you can refer to the link
(https://msdn.microsoft.com/en-us/library/office/dn450841.aspx#bk_File)
My example code is:
string resourceUrl = "https://<BaseURL>/sites/<SubSite>/_api/web/GetFileByServerRelativeUrl('/sites/<SubSite>/Documents/New Folder/xyz.docx')";
var wreq = WebRequest.Create(resourceUrl) as HttpWebRequest;
wreq.Headers.Remove("X-FORMS_BASED_AUTH_ACCEPTED");
wreq.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
wreq.Headers.Add("X-HTTP-Method", "DELETE");
//wreq.Headers.Add("Authorization", "Bearer " + AccessToken);
wreq.UseDefaultCredentials = true;
wreq.Method = "POST";
wreq.Accept = "application/json; odata=verbose";
wreq.Timeout = 1000000;
wreq.AllowWriteStreamBuffering = true;
wreq.ContentLength = 0;
string result = string.Empty;
string JsonResult = string.Empty;
try
{
WebResponse wresp = wreq.GetResponse();}
catch (Exception ex)
{
LogError(ex);
result = ex.Message;
}
Having tried the answers above and but still not getting the files deleted I found this and it works perfectly
var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(“FullSharePointURIofDocument“);
request.Timeout = System.Threading.Timeout.Infinite;
request.Credentials = new
System.Net.NetworkCredential(“SharePointUser“,”SharePointUserPassword“);
request.Method = “DELETE“;
var response = (System.Net.HttpWebResponse)request.GetResponse();
thanks to BizTalkBox

Categories