I need to create a table on Azure Synapse (schema and other details less important at the moment).
I found SynapseManagementClient, but besides getting a client (var client = new SynapseManagementClient(new Uri(synapseUri), credentials);), I didn't find any working example.
Any idea how to create a table on Azure Synapse with C#?
Create the Azure Synapse in azure portal.
Create SQL Pool.
Set the firewall settings to allow azure services and resources to access the workspace, else you will be getting forbidden error.
I have used the below code and able to create table in Azure synapse.
string apiUrl = "Azure Synapse Workspace URL";
string apiKey = "API Key";
string createTableStatement = "CREATE TABLE testTable (id int, name string)";
string sqlQuery = $"{createTableStatement};";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("spark-api-key", apiKey);
var content = new StringContent(sqlQuery, Encoding.UTF8, "application/json");
var response = client.PostAsync(apiUrl, content).Result;
response.EnsureSuccessStatusCode();
Console.WriteLine("Table created successfully!");
}
Table created successfully using the client in Azure Synapse.
Related
I am trying to upload a PDF file to the file field in the CRM entity. I followed the following document: https://learn.microsoft.com/en-us/powerapps/developer/data-platform/file-attributes#upload-file-data
Implemented the code of OAuth to generate an Access token using a Client ID and Client Secret. But I am getting a Bad Request as a response.
Entity name: msnfp_request
File field name: bna_file
var fileStream = System.IO.File.OpenRead(<file path>);
var url = new Uri("https://mydev.crm.dynamics.com/api/data/v9.1/msnfp_request(a528f300-7b53-ec11-8c62-0022482a2e7a)/bna_file);
AuthenticationContext authContext = new AuthenticationContext("https://login.microsoftonline.com/<domain>");
ClientCredential credential = new Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential(<client id>,<client secret>);
AuthenticationResult result = authContext.AcquireToken("https://mydev.crm.dynamics.com/", credential);
using (var req = new HttpRequestMessage(new HttpMethod("PATCH"), url))
{
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
req.Content = new StreamContent(fileStream);
req.Content.Headers.Add("Content-Type", "application/octet-stream");
req.Content.Headers.Add("x-ms-file-name", "test.pdf");
HttpClient Client = new HttpClient();
using (var response = await Client.SendAsync(req))
{
response.EnsureSuccessStatusCode();
}
}
What am I doing wrong in the above code?
I will troubleshoot to see if you are able to find out issues step by step.
Make sure the authentication is working after passing the token, as you are not getting 401 it should be fine. But you can do a simple GET request to cross check the connectivity is working
The plural entity name could be a problem. You can find the status code text to see any inner exception like "The resource could not be found". Pls try in case entity plural name is msnfp_requests then it should be like https://mydev.crm.dynamics.com/api/data/v9.1/msnfp_requests(a528f300-7b53-ec11-8c62-0022482a2e7a)/bna_file (wild guess :))
I have two web APIs applications developed in .Net core. I need to import Json data from the second application to the first. However,I have a security issue. I need to secure the access to the external API. How should I securely manage the connection between these two APIs.
For example, I need to secure the access to the URL in the code bellow => securely access to the covid API without another authentication.
PS: I'm using JWT token authentication in both applications
Best regards.
using (var client = new HttpClient())
{
string url = string.Format("https://covid19.mathdro.id/api");
var response = client.GetAsync(url).Result;
string responseAsString = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<CovidResult>(responseAsString);
}
If both APIs are protected by the same accessToken, then you can read the authorization header from the first request and pass it to the second request.
Something like this to read the header:
var authHeader = context.Request.Headers.Get("Authorization");
You should end up with authHeader equal to "Bearer ey...(a bunch of base64)"
Then add the auth header to the client:
var request = new HttpRequestMessage() {
RequestUri = new Uri("http://https://covid19.mathdro.id/api"),
Method = HttpMethod.Get,
};
...
request.Headers.Authorization.Add(new AuthenticationHeaderValue(authHeader));
var task = client.SendAsync(request)
I am attempting to wire up source control with continuous integration to an Azure Web App programmatically via C#. Historically I've used Azure PowerShell to do the same.
On the C# side, I am using the Microsoft.Azure.Management.Fluent libraries. The code to wire up source control is pretty straight forward:
await webApp.Update().DefineSourceControl().WithContinuouslyIntegratedGitHubRepository(GIT_URL).WithBranch(GIT_BRANCH).WithGitHubAccessToken(GIT_TOKEN).Attach().ApplyAsync();
This code runs for about 5 minutes and then returns the error:
{"Code":"BadRequest","Message":"Parameter x-ms-client-principal-name
is null or empty."}
I initially interpreted this to mean the Fluent libraries weren't passing a necessary value to the API, so I attempted to hit the API directly using Fluent libraries to abstract the authorization piece:
var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal( CLIENT_ID, CLIENT_SECRET, TENANT_ID, AzureEnvironment.AzureGlobalCloud);
var client = RestClient.Configure().WithEnvironment(AzureEnvironment.AzureGlobalCloud).WithCredentials(credentials).Build();
CancellationToken cancellationToken = new CancellationToken();
var request = new HttpRequestMessage(HttpMethod.Get, $"https://management.azure.com/subscriptions/{SUBSCRIPTION_ID}/resourcegroups/{RESOURCE_GROUP}?api-version=2019-10-01");
request.Headers.Add("x-ms-client-principal-name", USERNAME);
client.Credentials.ProcessHttpRequestAsync(request, cancellationToken).GetAwaiter().GetResult();
var httpClient = new HttpClient();
var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).GetAwaiter().GetResult();
var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
Several variations of this resulted in the same error referencing x-ms-client-principal-name. This lead me to believe the problem was with the token being used and the associated permissions. To test this, I ran the PowerShell script mentioned above, watched it run through Fiddler, and grabbed the token it used to complete. Using that token with basically the same code, it worked fine:
var token = "<THE TOKEN I COPIED FROM FIDDLER>";
CancellationToken cancellationToken = new CancellationToken();
var request = new HttpRequestMessage(requestType, $"https://management.azure.com/subscriptions/{SUBSCRIPTION_ID}/resourceGroups/{RESOURCE_GROUP}/providers/Microsoft.Web/sites/{WEB_APP}/sourcecontrols/web?api-version=2015-08-01");
request.Headers.Add("Authorization", $"Bearer {token}");
if ((requestType == HttpMethod.Put || requestType == HttpMethod.Post) && !string.IsNullOrEmpty(postData))
{
request.Content = new StringContent(postData, Encoding.UTF8, "application/json");
}
var httpClient = new HttpClient();
var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).GetAwaiter().GetResult();
var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
So now, it seems to just be a matter of getting the access token myself. This is where things have become difficult. If I obtain the token as the service principal, I end up with the same x-ms-client-principal-name that I started with:
public static string GetAuthToken(string tenantId, string clientId, string clientSecret)
{
var request = new HttpRequestMessage(HttpMethod.Post, $"https://login.microsoftonline.com/{tenantId}/oauth2/token");
request.Content = new StringContent($"grant_type=client_credentials&client_id={clientId}&client_secret={clientSecret}&resource=https://management.azure.com", Encoding.UTF8, "application/x-www-form-urlencoded");
CancellationToken cancellationToken = new CancellationToken();
var httpClient = new HttpClient();
var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).GetAwaiter().GetResult();
var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var auth = JsonConvert.DeserializeObject<AuthResponse>(result);
return auth.AccessToken;
}
When I attempt to obtain token using my username and password, I get an error back telling me:
AADSTS90002: Tenant '' not found. This may happen if there are no
active subscriptions for the tenant. Check to make sure you have the
correct tenant ID. Check with your subscription administrator.
Here's the code I use for that:
public static string GetAuthToken(string tenantId, string username, string password, string clientId, string clientSecret)
{
var request = new HttpRequestMessage(HttpMethod.Post, $"https://login.microsoftonline.com/{tenantId}/oauth2/token");
request.Content = new StringContent($"grant_type=password&username={username}&password={password}&client_id={clientId}&client_secret={clientSecret}&resource=https://management.azure.com", Encoding.UTF8, "application/x-www-form-urlencoded");
CancellationToken cancellationToken = new CancellationToken();
var httpClient = new HttpClient();
var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).GetAwaiter().GetResult();
var result = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var auth = JsonConvert.DeserializeObject<AuthResponse>(result);
return auth.AccessToken;
}
I cannot have the C# code invoke the PS script as a work-around as it requires Azure PowerShell which is not guaranteed to be on the machine running the code (Azure Web App) and cannot be installed due to Admin restrictions.
I need to be able to obtain an access token that also has permissions for azure dev ops (formally VSTS) so I can bind/wire-up source control for continuous integration. Any guidance that can help me get past this is much appreciated.
I was finally able to get it working. First, I had to create a new Azure AD User and grant it the necessary permissions; this would not work with my regular Azure Login. With the new user and permissions, I am able to successfully obtain token like so:
public static async Task<string> GetAccessToken(string clientId, string userName, string password)
{
AuthenticationContext authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/<TENANT_ID>");
var resourceId = "https://management.azure.com";
var result = await authenticationContext.AcquireTokenAsync(resourceId, clientId, new UserPasswordCredential(userName, password));
return result.AccessToken;
}
This token then works for wiring up source control and continuous integration.
I want to call graph api, https://graph.windows.net for that I am using a delegated permission as below for token
UserPasswordCredential credentials = new UserPasswordCredential("username", "password");
AuthenticationContext authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", "mytenant.onmicrosoft.com"));
var accessToken = authContext.AcquireTokenAsync("https://graph.windows.net", clientId, credentials).Result.AccessToken;
I am not a tenant admin and in AAD and I cannot add specific Applications as an owner for app authentication. This was working in full .net is there a workaround for this in .net standard? As I cannot use app authentication in this scenario.
I am trying to convert and webjob to an Azure function.
is there a workaround for this in .net standard?
Yes, we could use the rest API to get the token directly.
Post https://login.windows.net/<tenant-id>/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=password
&resource={resource}
&username={username}
&password={password}
&client_id={client-id}
The following is the demo code to get access token
var tenantId = "xxx.onmicrosoft.com";
var userName = "xxx#xxxx.onmicrosoft.com";
var password = "xxxxxx";
var clientId = "xxxxxxx";
using (HttpClient client = new HttpClient())
{
var tokenEndpoint = $"https://login.windows.net/{tenantId}/oauth2/token";
var accept = "application/json";
client.DefaultRequestHeaders.Add("Accept", accept);
string postBody = $"resource=https://graph.windows.net/&client_id={clientId}&grant_type=password&username={userName}&password={password}";
using (HttpResponseMessage response = await client.PostAsync(tokenEndpoint, new StringContent(postBody, Encoding.UTF8, "application/x-www-form-urlencoded")))
{
if (response.IsSuccessStatusCode)
{
var jsonresult = JObject.Parse(await response.Content.ReadAsStringAsync());
var token = (string)jsonresult["access_token"];
}
}
}
Note: Azure AD native application is requried.
I am running into an odd issue with trying to access a thumbnail image stored on O365 video via C#. I can access the REST API with no issue at all, I just add the Authentication: Bearer <token> to the header and I am off an running. The trouble is with a basic image URL that I get back from a specific video.
https://<mytenant>.sharepoint.com/portals/Channel1/pVid/myvideo.mp4.PNG?VideoPreview=1
When I access that URL from a browser it works 100% of the time. When I try to access it via the httpclient object, I am getting a 401 Unauthorized error.
The best I can figure is that the authorization header token is not being honored when accessing a basic URL. Which makes me thing that I need something else like a cookie? However I cannot seem to figure out which one. Looking for any advice :)
Pass credentials instead and yes you need an authentication cookie. Here is a sample:
private static async Task<string>getWebTitle(string webUrl)
{
//Creating Password
const string PWD = "softjam.1";
const string USER = "bubu#zsis376.onmicrosoft.com";
const string RESTURL = "{0}/_api/web?$select=Title";
//Creating Credentials
var passWord = new SecureString();
foreach (var c in PWD) passWord.AppendChar(c);
var credential = new SharePointOnlineCredentials(USER, passWord);
//Creating Handler to allows the client to use credentials and cookie
using (var handler = new HttpClientHandler() { Credentials = credential })
{
//Getting authentication cookies
Uri uri = new Uri(webUrl);
handler.CookieContainer.SetCookies(uri, credential.GetAuthenticationCookie(uri));
//Invoking REST API
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(string.Format(RESTURL, webUrl)).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
string jsonData = await response.Content.ReadAsStringAsync();
return jsonData;
}
}
}