We have an ASP.NET WebAPI which generates a custom document using the TFS SDK. We attempted to wrap the entire call stack for the SDK inside a C# impersonation wrapper. Our document is returned corrupted because the TFS client is not authenticating under the IIS Network Service but is correctly returned with data when we set the App Pool identity to a specific user. The EnsureAuthenticated comes back true. The TestManagementService is not null. The ProjectName parameter is not empty and has a valid ProjectName;
[Route("generatetestplan")]
[HttpPost]
public HttpResponseMessage Post([FromBody]TestPlanRequest Request)
{
var wi = (WindowsIdentity)HttpContext.Current.User.Identity;
HttpResponseMessage Res = new HttpResponseMessage(HttpStatusCode.OK);
WindowsIdentity.RunImpersonated(wi.AccessToken, () =>
{
using (var handler = new HttpClientHandler { UseDefaultCredentials = true })
using (var client = new HttpClient(handler))
{
Res = GenerateTestPlan(Request, Res);
}
});
return Res;
}
public HttpResponseMessage GenerateTestPlan(TestPlanRequest Request, HttpResponseMessage Res)
{
var TestResultsGen = new TestResultsGenerator(Request.ProjectName, Request.TestPlanId);
TestResultsGen.Generate();
var Bytes = TestResultsGen.FBytes;
Res.Content = new ByteArrayContent(Bytes);
Res.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return Res;
}
public TestResultsGenerator(string ProjectName, int TestPlanId)
{
TfsTeamProjectCollection = AuthenticateToCollection();
this.TestPlanId = TestPlanId;
this.ProjectName = ProjectName;
try
{
TestManagementService = TfsTeamProjectCollection.GetService<ITestManagementService>();
TeamProject = TestManagementService.GetTeamProject(ProjectName);
}
catch(Exception e)
{
logger.Error(DateTime.Now.ToString() + " Test Service Error: " + e.ToString());
}
}
public static TfsTeamProjectCollection AuthenticateToCollection()
{
var server = ConfigurationManager.AppSettings["TFS"];
TfsTeamProjectCollection TfsCollection = new TfsTeamProjectCollection(new Uri(server), new Microsoft.VisualStudio.Services.Common.VssCredentials());
try
{
TfsCollection.EnsureAuthenticated();
}
catch (Exception e)
{
logger.Error(e.ToString());
AuthenticateToCollection();
}
return Tfs
Related
I am fairly new to API's. I am writing a "simple" API that will convert .docx files to .pdf files and return the pdf's back to the client for saving. I have the code working for a single file but I wanted to code the API to handle multiple files in a single request. Now the API is not receiving the request. I can provide the working code with a single file if requested.
I am sure I am missing something simple. Please see below and see if anyone see's something that I could be doing better or why the API is not receiving the POST request.
Client:
List<string> documents = new List<string>();
private async void btnConvert_Click(object sender, EventArgs e)
{
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
client.BaseAddress = new Uri(BaseApiUrl);
//client.DefaultRequestHeaders.Add("Accept", "application/json");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);
foreach (string s in docPaths)
{
byte[] bte;
bte = File.ReadAllBytes(docPath);
string data = JsonConvert.SerializeObject(Convert.ToBase64String(bte));
documents.Add(data);
}
using (var formData = new MultipartFormDataContent())
{
foreach (string s in documents)
{
//add content to form data
formData.Add(new StringContent(s, Encoding.UTF8, "application/json"));
}
// List of Http Reponse Messages
var conversions = documents.Select(doc => client.PostAsync(BaseApiUrl + ApiUrl, formData)).ToList();
//Wait for all the requests to finish
await Task.WhenAll(conversions);
//Get the responses
var responses = conversions.Select
(
task => task.Result
);
foreach (var r in responses)
{
// Extract the message body
var s = await r.Content.ReadAsStringAsync();
SimpleResponse res = JsonConvert.DeserializeObject<SimpleResponse>(s);
if (res.Success)
{
byte[] pdf = Convert.FromBase64String(res.Result.ToString());
// Save the PDF here
}
else
{
// Log issue
}
}
}
}
API: This is not getting the request so this function is not complete. I need to figure out why it not being hit.
[HttpPost]
public async Task<List<SimpleResponse>> Post([FromBody]string request)
{
var response = new List<SimpleResponse>();
Converter convert = new Converter();
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var requestContents in provider.Contents)
{
try
{
//var result = convert.CovertDocToPDF(requestContents, WebConfigurationManager.AppSettings["tempDocPath"], WebConfigurationManager.AppSettings["tempPdfPath"]);
//response.Add(new SimpleResponse() { Result = result, Success = true });
}
catch (Exception ex)
{
response.Add(new SimpleResponse() { Success = false, Exception = ex, Errors = new List<string>() { string.Format("{0}, {1}", ex.Message, ex.InnerException?.Message ?? "") } });
}
}
return response;
}
SimpleResponse Model:
public class SimpleResponse
{
public object Result { get; set; }
public bool Success { get; set; }
public Exception Exception { get; set; }
public List<string> Errors { get; set; }
}
UPDATE
Did suggestions made by #jdweng and I am getting a null response on the API POST
Client:
public async void btnConvert_Click(object sender, EventArgs e)
{
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
client.BaseAddress = new Uri(BaseApiUrl);
client.DefaultRequestHeaders.Add("Accept", "application/json");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));//application/json
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);
List<string> requests = new List<string>();
byte[] bte;
// New Code per the suggestion
foreach (string s in docPaths)
{
bte = File.ReadAllBytes(s);
requests.Add(Convert.ToBase64String(bte));
}
// End new code
string data = JsonConvert.SerializeObject(requests);
request.Content = new StringContent(data, Encoding.UTF8, "application/json");
HttpResponseMessage response1 = client.PostAsync(BaseApiUrl + ApiUrl, request.Content).Result;
Task<string> json = response1.Content.ReadAsStringAsync();
SimpleResponse response = JsonConvert.DeserializeObject<SimpleResponse>(json.Result);
//result = JsonConvert.DeserializeObject(result).ToString();
if (response.Success)
{
bte = Convert.FromBase64String(response.Result.ToString());
if (File.Exists(tempPdfPath))
{
File.Delete(tempPdfPath);
}
System.IO.File.WriteAllBytes(tempPdfPath, bte);
}
else
{
}
}
}
Server:
[HttpPost]
public async Task<List<SimpleResponse>> Post([FromBody]string request)
{
// The request in NULL....
List<SimpleResponse> responses = new List<SimpleResponse>();
List<string> resp = JsonConvert.DeserializeObject(request) as List<string>;
try
{
Converter convert = new Converter();
foreach (string s in resp)
{
var result = convert.CovertDocToPDF(request, WebConfigurationManager.AppSettings["tempDocPath"], WebConfigurationManager.AppSettings["tempPdfPath"]);
responses.Add(new SimpleResponse()
{
Result = result,
Success = true
});
}
}
catch (Exception ex)
{
responses.Add(new SimpleResponse()
{
Result = null,
Success = true,
Exception = ex,
Errors = new List<string>() { string.Format("{0}, {1}", ex.Message, ex.InnerException?.Message ?? "") }
});
}
return responses;
}
I have finally solved the issues and can now successfully send multiple .docx files to the API and get the .pdf files back from the API. Now I want to figure out how to send each files on it's own thread instead of all together.
Client:
public async void btnConvert_Click(object sender, EventArgs e)
{
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
client.BaseAddress = new Uri(BaseApiUrl);
client.DefaultRequestHeaders.Add("Accept", "application/json");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);
List<string> requests = new List<string>();
byte[] bte;
foreach (string s in docPaths)
{
bte = File.ReadAllBytes(s);
requests.Add(Convert.ToBase64String(bte));
}
var data = JsonConvert.SerializeObject(requests);
request.Content = new StringContent(data, Encoding.UTF8, "application/json");
HttpResponseMessage response1 = await client.PostAsync(BaseApiUrl + ApiUrl, request.Content);
Task<string> json = response1.Content.ReadAsStringAsync();
var response = JsonConvert.DeserializeObject<List<SimpleResponse>>(json.Result);
foreach (SimpleResponse sr in response)
{
if (sr.Success)
{
bte = Convert.FromBase64String(sr.Result.ToString());
string rs = RandomString(16, true);
string pdfFileName = tempPdfPath + rs + ".pdf";
if (File.Exists(pdfFileName))
{
File.Delete(pdfFileName);
}
System.IO.File.WriteAllBytes(pdfFileName, bte);
}
else
{
}
}
}
}
API:
[HttpPost]
public async Task<List<SimpleResponse>> Post([FromBody] List<string> request)
{
List<SimpleResponse> responses = new List<SimpleResponse>();
try
{
Converter convert = new Converter();
foreach (string s in request)
{
var result = convert.CovertDocToPDF(s, WebConfigurationManager.AppSettings["tempDocPath"], WebConfigurationManager.AppSettings["tempPdfPath"]);
responses.Add(new SimpleResponse()
{
Result = result,
Success = true
});
}
}
catch (Exception ex)
{
responses.Add(new SimpleResponse()
{
Result = null,
Success = true,
Exception = ex,
Errors = new List<string>() { string.Format("{0}, {1}", ex.Message, ex.InnerException?.Message ?? "") }
});
}
return responses;
}
I am using rest end point and don't get folder id on creation. It should be in response but not there.
Folder is getting created successfully.
url: https://www.googleapis.com/drive/v3/files
public static async void CreateFolder(string accessToken, string brandFolderName)
{
var gDriveItems = await GetFoldersByBrand(accessToken,brandFolderName);
if (gDriveItems.Any(x=>x.Name.ToLower() == brandFolderName.ToLower()))
{
return;
}
var request = new HttpRequestMessage(HttpMethod.Post, "drive/v3/files");
request.Headers.Add("Authorization", "Bearer "+ accessToken);
request.Headers.Add("Accept","application/json");
JsonObject jsonFolderObject = new JsonObject();
jsonFolderObject.Add("name", brandFolderName);
jsonFolderObject.Add("mimeType", "application/vnd.google-apps.folder");
var data = JsonConvert.SerializeObject(jsonFolderObject);
request.Content = new StringContent(data, Encoding.UTF8, "application/json");
var responce = await _httpClient.SendAsync(request);
var mm = responce.Content.ReadAsStringAsync();
responce.EnsureSuccessStatusCode();
}
For reference, here's my code to add a new folder.
I use Google.Apis.Drive.v3
service is an instance of DriveService with the relevant scope to create a folder/file.
This will give me the Id of the new folder in the result
private static async Task<File> CreateRankingsFolder(DriveService service,
string driveId,
string parentId,
string folderName = "YOURFOLDERNAME")
{
File result = null;
try
{
File body = new File();
body.Name = folderName;
body.MimeType = "application/vnd.google-apps.folder";
body.DriveId = driveId;
if (!string.IsNullOrEmpty(parentId))
{
var _parents = new List<string>()
{
parentId
};
body.Parents = _parents;
}
// service is an authorized Drive API service instance
var req = service.Files.Create(body);
result = await req.ExecuteAsync();
}
catch(Exception e)
{
}
return result;
}
I am working on an asp.net web application where I have to create users directly in Tableau Server using Rest API and C#. The users are local users and not AD or SAML users.
I have coded the part however, I am getting Unauthorised as the result. Below is my code.
public static string site_id { get; set; }
public static string token { get; set; }
static void Main(string[] args)
{
CallWebAPIAsync().Wait();
}
static async Task CallWebAPIAsync()
{
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
client.BaseAddress = new Uri("https://serverurl.com");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
SignIn(client);
Users(client, site_id, token);
CreateUser(client, site_id, token);
}
Console.Read();
}
public class CustomXmlMediaTypeFormatter : XmlMediaTypeFormatter
{
public CustomXmlMediaTypeFormatter()
{
UseXmlSerializer = true;
WriterSettings.OmitXmlDeclaration = false;
}
}
public static tableauCredentialsType SignIn(HttpClient client)
{
var name = "Administrator";
var password = "Password";
var site = string.Empty;
var tableauCredentialsType = new tsRequest()
{
Item = new tableauCredentialsType
{
name = name,
password = password,
site = new siteType() { contentUrl = site }
}
};
var httpContent = new ObjectContent<tsRequest>(tableauCredentialsType, new CustomXmlMediaTypeFormatter());
var httpResponseMessage = client.PostAsync("/api/3.2/auth/signin", httpContent).Result;
if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
throw new Exception(string.Format("Unable to login to the server", site, name));
var responseLogin = httpResponseMessage.Content.ReadAsAsync<tsResponse>(new List<MediaTypeFormatter>() { new CustomXmlMediaTypeFormatter() }).Result;
var resultTableauCredentialsType = ((tableauCredentialsType)responseLogin.Items[0]);
site_id = resultTableauCredentialsType.site.id;
token = resultTableauCredentialsType.token;
return resultTableauCredentialsType;
}
public static userType CreateUser(HttpClient client, string siteid, string auth_token)
{
var name = "user#domain.com";
var userType = new tsRequest()
{
Item = new userType
{
name = name,
siteRole = siteRoleType.ExplorerCanPublish,
authSetting = siteUserAuthSettingType.ServerDefault
}
};
var httpContent = new ObjectContent<tsRequest>(userType, new CustomXmlMediaTypeFormatter());
client.DefaultRequestHeaders.Add("x-tableau-auth", auth_token);
var uri = string.Format("/api/3.2/sites/{0}/users", siteid);
var httpResponseMessage = client.PostAsync(uri, httpContent).Result;
if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
throw new Exception(string.Format("Unable to create user in the server", siteid, name));
var responseLogin = httpResponseMessage.Content.ReadAsAsync<tsResponse>(new List<MediaTypeFormatter>() { new CustomXmlMediaTypeFormatter() }).Result;
var resultTableauCredentialsType = ((userType)responseLogin.Items[0]);
return resultTableauCredentialsType;
}
I was able to successfully login into the server and was also able to provide the x-tableau-auth to my client headers.
The code is working fine except the post sync method in Create user method. Once the code executes, it throws UnAuthorized error as the response from the server. My user is the administrator in Tableau Server and when I query the workbooks and users in Tableau Server with the same x-tableau-auth, it's working fine.
I am not good in API programming and need some help in solving out this issue. Any help is highly appreciated.
I am new to API coding and working on a module which signs in to Tableau Server and gets the list of workbooks stored in a site. The code is to be written in C# using the Tableau Rest API.
I was able to sign in to Tableau server successfully using the Rest API. However, I was not able to query the workbooks. Below is my code.
class Program
{
static HttpClient client = new HttpClient();
public static string site_id { get; set;}
public static string token { get; set; }
static void Main(string[] args)
{
CallWebAPIAsync().Wait();
}
static async Task CallWebAPIAsync()
{
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
client.BaseAddress = new Uri("https://my server url.com");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
SignIn(client);
Workbooks(client, site_id, token);
}
Console.Read();
}
public class CustomXmlMediaTypeFormatter : XmlMediaTypeFormatter
{
public CustomXmlMediaTypeFormatter()
{
UseXmlSerializer = true;
WriterSettings.OmitXmlDeclaration = false;
}
}
public static tableauCredentialsType SignIn(HttpClient client)
{
var name = "Administrator";
var password = "password";
var site = "";
var tableauCredentialsType = new tsRequest()
{
Item = new tableauCredentialsType
{
name = name,
password = password,
site = new siteType() { contentUrl = site }
}
};
var httpContent = new ObjectContent<tsRequest>(tableauCredentialsType, new CustomXmlMediaTypeFormatter());
var httpResponseMessage = client.PostAsync("/api/3.2/auth/signin", httpContent).Result;
if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
throw new Exception(string.Format("Unable to login to the server", site, name));
var responseLogin = httpResponseMessage.Content.ReadAsAsync<tsResponse>(new List<MediaTypeFormatter>() { new CustomXmlMediaTypeFormatter() }).Result;
var resultTableauCredentialsType = ((tableauCredentialsType)responseLogin.Items[0]);
site_id = resultTableauCredentialsType.site.id;
token = resultTableauCredentialsType.token;
return resultTableauCredentialsType;
}
public static IList<workbookType> Workbooks(HttpClient client, string siteid, string auth_token, int pageSize = 100, int pageNumber =1)
{
IList<workbookType> results = new List<workbookType>();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("x-tableau-auth", auth_token);
var query = client.GetAsync(string.Format("/api/3.2/sites/{0}/workbooks", siteid, pageSize, pageNumber)).Result;
if(query.StatusCode == System.Net.HttpStatusCode.OK)
{
var result = query.Content.ReadAsAsync<tsResponse>(new List<MediaTypeFormatter>() { new CustomXmlMediaTypeFormatter() }).Result;
var pagination = (paginationType)result.Items[0];
var workbooks = ((workbookListType)result.Items[1]).workbook.AsEnumerable();
for (int i=2; i < pageNumber; i++)
{
query = client.GetAsync(string.Format("/api/3.2/sites/{0}/workbooks", siteid, pageSize, i)).Result;
if(query.StatusCode == System.Net.HttpStatusCode.OK)
{
result = query.Content.ReadAsAsync<tsResponse>(new List<MediaTypeFormatter>() { new CustomXmlMediaTypeFormatter() }).Result;
workbooks = workbooks.Concat(((workbookListType)result.Items[1]).workbook.AsEnumerable());
}
}
results = workbooks.ToList();
}
return results;
}
}
When I try to run the Workbooks function in the above code I am getting 401-Unauthorized error. I came to know that I need to pass the X-tableau_auth so that I will have the authentication done while querying for the workbooks. However, I was not able to get that properly.
Can anyone help me with this?
The header information can be passed using the DefaultRequestHeaders Add method.
You can try something like
client.DefaultRequestHeaders.Add("x-tableau-auth", "tokenvalue");
Also the api parameters is incorrect. You can refer to the API guide provided by Tableau
Did you check the Url that you're using to fetch the list of workbooks? I checked with Tableau's API documentation, the Url format looks different, try updating your code
string.Format("/api/{0}/sites/site-id/workbooks", siteid, pageSize, i)
to
string.Format("/api/3.4/sites/{0}/workbooks", siteid)
Here I assumed you're using 3.4 version api.
I'd also recommend using some Rest Clients to test these Apis before you code.
We use Windows Azure website management library and create a web app programmatically by using C# code but we cannot create a virtual directory inside a web app. please help me how to create virtual directory inside a web app programmatically
My Code here
var websiteManagementClient =
CloudContext.Clients.CreateWebSiteManagementClient(Credentials);
var webSpaces = websiteManagementClient.WebSpaces.List();
var webSpace = webSpaces.FirstOrDefault(x => x.GeoRegion == "South Central US");
if (webSpace == null)
{
throw new Exception(string.Format("No webspace for region {0} found", "South Central US"));
}
var webHostingPlans = websiteManagementClient.WebHostingPlans.List(webSpace.Name);
var webHostingPlan = webHostingPlans.FirstOrDefault();
if (webHostingPlan == null)
{
throw new Exception(string.Format("No webhostingplan found"));
}
try
{
var website = websiteManagementClient.WebSites.Get(webSpace.Name, "MyAzureTestSite", null);
if (website != null)
{
throw new Exception(string.Format("The website {0} already exists", ""));
}
}
catch (Exception)
{
}
var websiteCreateParams = new WebSiteCreateParameters();
websiteCreateParams.Name = "MyAzureTestSite";
websiteCreateParams.ServerFarm = webHostingPlan.Name;
websiteManagementClient.WebSites.Create(webSpace.Name, websiteCreateParams);
At first I tried to create virtual directory with the help of Azure SDK but was not successful. Finally, I used http request to create it.
If you can use this method, you can check it out on my blog.
http://kapiltak.blogspot.in/2015/10/how-to-create-virtual-application-in.html
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Threading;
namespace ConsoleApplication1
{
public class Azure
{
private string loginpath = "https://login.windows.net/{0}";
private string apiEndpoint = "https://management.azure.com/";
//Fill these up
private string webSiteName = "{your webSiteName}";
private string webSpaceName = "Default-Web-SoutheastAsia"; //Insert your webSpaceName here
private string tenantId = "{your tenantId}";
private string clientId = "{your client Id}";
private string subscriptionId = "{your subscription Id}";
//Not needed to set in console app because a function is called to get the token
//string token = "";
public void CreateVD(string name)
{
try
{
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(String.Format(#"https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Web/sites/{2}/config/web?api-version=2015-08-01",subscriptionId,webSpaceName,webSiteName));
request.Headers.Add("x-ms-version", "2013-03-01");
request.ContentType = "application/json";
var token = GetAuthorizationHeader();
request.Headers.Add("Authorization", "Bearer" + " " + token);
System.Net.WebResponse response = request.GetResponse();
string data = "";
using (System.IO.Stream stream = response.GetResponseStream())
{
System.IO.StreamReader sr = new System.IO.StreamReader(stream);
data = sr.ReadToEnd();
sr.Close();
stream.Close();
Console.WriteLine("data found");
}
if (data == "")
{
Console.WriteLine("Error in collecting data");
return;
}
string path = name, directory = name;
data = data.Replace("virtualApplications\":[", "virtualApplications\":[{\"virtualPath\":\"/" + path + "\",\"physicalPath\":\"site\\\\wwwroot\\\\" + directory + "\",\"preloadEnabled\":false,\"virtualDirectories\":null},");
request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(String.Format(#"https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Web/sites/{2}/config/web?api-version=2015-08-01",subscriptionId,webSpaceName,webSiteName));
request.Headers.Add("x-ms-version", "2013-03-01");
request.ContentType = "application/json";
request.AllowWriteStreamBuffering = false;
request.Accept = "Accept=application/json";
request.SendChunked = false;
request.Headers.Add("Authorization", "Bearer" + " " + token);
request.ContentLength = data.Length;
request.Method = "PUT";
System.IO.StreamWriter sw = new System.IO.StreamWriter(request.GetRequestStream());
sw.Write(data);
sw.Close();
response = request.GetResponse();
using (System.IO.Stream stream = response.GetResponseStream())
{
data = (new System.IO.StreamReader(stream)).ReadToEnd();
Console.WriteLine("DONE");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
private string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext(string.Format(loginpath, tenantId));
var thread = new Thread(() =>
{
result = context.AcquireToken(apiEndpoint, clientId, new Uri(redirectUri));
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
}
}
This code can be used to create virtual directory from website itself but you cannot use "GetAuthorizationHeader()" method to get the token. Instead you can get the token by running the console app once and use a breakpoint to get the string value. Use this value in the code and remove the "GetAuthorizationHeader()" method.