Updates a single work item Azure Devops using Asp.net - c#

I am trying to update work item in Azure devops using this API : https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/update?view=azure-devops-rest-5.1#update-a-field .
But i can't find the way to do this.

You should use http client to call Rest API. Sample code as below:
private readonly WorkItemTrackingHttpClient _workItemTrackingHttpClient;
public RestApi(string baseUrl, string pat)
{
var vssConnection = new VssConnection(new Uri(baseUrl), new VssBasicCredential(string.Empty, pat));
_workItemTrackingHttpClient = vssConnection.GetClient<WorkItemTrackingHttpClient>();
var document = new JsonPatchDocument();
document.Add(new JsonPatchOperation()
{
Operation = Operation.Add,
Path = "/fields/Microsoft.VSTS.Scheduling.Effort",
Value = 1
});
var workItem = _workItemTrackingHttpClient.UpdateWorkItemAsync(document, 233843).Result;
}
Besides, you could also use client API, details you could take a look at our official doc here-- Fetch work items with queries programmatically in Azure DevOps Services

Related

Getting error while using DataFactoryManagementClient.pipelines method

I am trying to automate ADF pipeline runs from .NET. Was able to create a client and when I try to do the below call
var pipeline = client.Pipelines.Get(resourceGroup, dataFactoryName, "test_1");
I am getting the error as Microsoft.Rest.Azure.CloudException: 'The document could not be retrieved because it does not exist.
Complete code below:
// Authenticate and create a data factory management client
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(applicationId)
.WithAuthority("https://login.microsoftonline.com/" + tenantID)
.WithClientSecret(authenticationKey)
.WithLegacyCacheCompatibility(false)
.WithCacheOptions(CacheOptions.EnableSharedCacheOptions)
.Build();
AuthenticationResult result = await app.AcquireTokenForClient(new string[] { "https://management.azure.com//.default" }).ExecuteAsync();
ServiceClientCredentials cred = new TokenCredentials(result.AccessToken);
DataFactoryManagementClient client = new DataFactoryManagementClient(cred)
{
SubscriptionId = subscriptionId
};
Loos like it was a silly mistake. pipeline, I was trying to access from here was deleted by another process and hence this call failed.

Updating Azure Application via Microsoft Graph SDK

I am using the Microsoft Graph SDK (https://github.com/microsoftgraph/msgraph-sdk-dotnet) in my .NET Core 3.1 project logged in to my Service Principal. I can retrieve the Azure Application's Web Reply URLs:
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var rootItem = await graphClient.Applications.Request().GetAsync();
Microsoft.Graph.Application app = new Microsoft.Graph.Application();
foreach (var item in rootItem)
{
if (item.DisplayName.Equals("MyApp"))
{
app = item;
}
}
I am able to retrieve the actual Application object just fine. My question is, how do I update app.Web.RedirectUris through the SDK? I am able to do so via the Azure CLI with az ad app update --id <my_app_id> --reply-urls <url_1> <url_2>
You need to get an Microsoft.Graph.IApplicationRequestBuilder for the specific Application and then call UpdateAsync() method.
var rootItem = await client.Applications.Request().GetAsync();
Microsoft.Graph.Application app = new Microsoft.Graph.Application();
foreach (var item in rootItem)
{
if (item.DisplayName.Equals("MyApp"))
{
app = item;
app.Web.RedirectUris = new List<string> { "uri1", "uri2" };
await client.Applications[app.Id].Request().UpdateAsync(app);
}
}

how to create a web service for microsoft graph (C#)

I've recently started working as a junior c# developer. My boss asked me to build methods to CRUD teams in our AAD using the microsoft graph API. I've achieved this with a test application like that:
public async Task<string> createTeam()
{
// readying data from registry
var clientId = "********************"; //application (client) ID
var clientSecret = "********************";
var redirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient";
var authority = "https://login.microsoftonline.com/********************/v2.0";
var cca = ConfidentialClientApplicationBuilder.Create(clientId)
.WithAuthority(authority)
.WithRedirectUri(redirectUri)
.WithClientSecret(clientSecret)
.Build();
List<string> scopes = new List<string>
{
"https://graph.microsoft.com/.default"
};
//
var authenticationProvider = new MsalAuthenticationProvider(cca, scopes.ToArray());
//
GraphServiceClient graphClient = new GraphServiceClient(authenticationProvider);
// Code to create a Team
var team = new Team
{
DisplayName = "0000My Sample Team",
Description = "My Sample Team’s Description",
AdditionalData = new Dictionary<string, object>()
{
{"template#odata.bind", "https://graph.microsoft.com/v1.0/teamsTemplates('standard')"}
}
};
var result = await graphClient.Teams.Request().AddAsync(team);
return result.DisplayName;
}
With that piece of code working, I've created an asp.net web Application (.net framework) and added the class to it. The plan was to deploy it to an IIS server and and publish the methods as web services.
[WebMethod]
public async Task<string> createTeamAsync()
{
//The class where my methods reside
TeamServices ts = new TeamServices();
var result = await ts.createTeam();
return "OK";
}
I registered the app and deployed but when I try to use it, it does not create any Team.
Do you know what I'm doing wrong of what I should learn next get the app working? Im just a few weeks in c# and I'm completely lost in all that .net echosystem
Thanks in advance

Wrong client IP Adress using .NET Core 3.1 and HttpContext

I want to get my client's IP Address (for example, Chrome browser) and then use it to generate SAS token for my blob storage resources.
For this im using this lines of code:
// In Startup.cs class:
services.AddHttpContextAccessor();
// In controller method:
// _httpContextAccessor is IHttpContextAccessor interface
var clientIpAddress = _httpContextAccessor.HttpContext.Request.HttpContext.Connection.RemoteIpAddress;
var blobClient = blobContainerClient.GetBlobClient();
var blobSasBuilder = new BlobSasBuilder
{
StartsOn = now,
ExpiresOn = now.AddMinutes(10),
BlobContainerName = blobClient.BlobContainerName,
IPRange = new SasIPRange(clientIpAddress) // im using clientIpAddress here
};
When i check my ip in https://www.myip.com/ site i get the ip that works with Azure portal gui for generating sas tokens (after generating it i can access resources on blob)
When i deploy my app to Azure the IP is completly diffrent than my ip from https://www.myip.com/ site and im not allowd to generate sas token for my chrome browser.
My question is, why when i deployed my App to Azure HttpContext returns wrong client Ip adress?
Per my understanding, you want to generate a SAS token for requesting a client with the client's public IP address limit. I write a simple controller which could meet your requirement:
using System;
using Azure.Storage.Blobs;
using Azure.Storage.Sas;
using Microsoft.AspNetCore.Mvc;
namespace getSasTest.Controllers
{
[ApiController]
[Route("[controller]")]
public class SasTokenController : ControllerBase
{
[HttpGet]
public string get()
{
var remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;
var connstr = "<your connection string here>";
var container = "files";
var blob = "test.txt";
var blobClient = new BlobContainerClient(connstr,container).GetBlobClient(blob);
var blobSasBuilder = new BlobSasBuilder
{
BlobContainerName = blobClient.BlobContainerName,
BlobName = blobClient.Name,
IPRange = new SasIPRange(remoteIpAddress),
};
blobSasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(10);
blobSasBuilder.SetPermissions(BlobSasPermissions.Read);
var sas = blobClient.GenerateSasUri(blobSasBuilder);
return sas.ToString();
}
}
}
You can try to get an SAS token for test here:
https://stanwinapp.azurewebsites.net/sastoken
Result:
Use this token to access the blob:
It does not work locally.

Programmatically register app in azure active directory using graph api

I am trying to register an application in Azure AD using graph API, I have a method CallRestAPI which will make the request.
Below is the code
public async Task<Response> AzureADApp()
{
Response responseMessage = new Response();
try
{
var token = GenerateToken();
List<(string, string)> listHeaders = new List<(string, string)>();
listHeaders.Add(("Authorization", string.Concat("Bearer" + " " + token)));
listHeaders.Add(("Content-Type", "application/json"));
List<(string, string)> param = new List<(string, string)>();
param.Add(("displayName", "VS1Application123"));
param.Add(("homepage", "https://localhost:44358/"));
param.Add(("identifierUris", "https://G7CRM4L/6958490c-21ae-4885-804c-f03b3add87ad"));
string callUrl = "https://graph.windows.net/G7CRM4L/applications/?api-version=1.6";
var result = CallRestAPI(callUrl, "", Method.POST, listHeaders, param);
}
catch (Exception ex)
{
responseMessage.StatusCode = Convert.ToInt16(HttpStatusCode.InternalServerError);
}
return responseMessage;
}
public async Task<IRestResponse> CallRestAPI(string BaseAddress, string SubAddress, Method method, List<(string, string)> headersList = null, List<(string, string)> paramsList = null)
{
var call = new RestClient(BaseAddress + SubAddress);
var request = new RestRequest(method);
if (headersList != null)
{
foreach (var header in headersList)
{
request.AddHeader(header.Item1, header.Item2);
}
}
if (paramsList != null)
{
foreach (var param in paramsList)
{
request.AddParameter(param.Item1, param.Item2);
}
}
var response = call.ExecuteTaskAsync(request);
return response.Result;
}
I think the way I am sending parameters in the body is not correct can anyone guide me how to make this code work or is there a better way to achieve the same?
Thank you.
A better way to achieve the same i.e. register an app with Azure AD will be to make use of Azure AD Graph Client Library
I say it's a better approach because when you use the client library you reap multiple benefits like no raw HTTP request handling, writing more convenient and declarative C# code, depending on a well tested library, async support etc.
Underlying Graph API used will still be the same I suppose
POST https://graph.windows.net/{tenant-id}/applications?api-version=1.6
Here is sample code (C#) to create an Azure AD application
Notice that I've kept app.PublicClient flag as true to register as a native application. You can set it to false if you want to register it as a web application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.ActiveDirectory.GraphClient;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
namespace CreateAzureADApplication
{
class Program
{
static void Main(string[] args)
{
ActiveDirectoryClient directoryClient;
ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(new Uri("https://graph.windows.net/{yourAADGUID}"),
async () => await GetTokenForApplication());
Application app = new Application();
app.DisplayName = "My Azure AD Native App";
app.PublicClient = true;
app.Homepage = "https://myazureadnativeapp";
activeDirectoryClient.Applications.AddApplicationAsync(app).GetAwaiter().GetResult();
}
public static async Task<string> GetTokenForApplication()
{
AuthenticationContext authenticationContext = new AuthenticationContext(
"https://login.microsoftonline.com/{yourAADGUID}",
false);
// Configuration for OAuth client credentials
ClientCredential clientCred = new ClientCredential("yourappclientId",
"yourappclientsecret"
);
AuthenticationResult authenticationResult =
await authenticationContext.AcquireTokenAsync("https://graph.windows.net", clientCred);
return authenticationResult.AccessToken;
}
}
}
Setup: I have an application registered in Azure AD, which has required permissions as application permission - Read and Write all applications and grant permissions is done for this app. Now using this application's client id and client secret, a token is acquired and Azure AD Graph API is called to create an application. It is not mandatory to use application permissions, you can also use delegated permissions by prompting user for credentials. See links to more detailed examples (old ones but still useful).
Console Application using Graph client library
Web app calls Graph using Graph client library
Azure AD Graph Client Library 2.0 Announcement page
On a side note, you could do this using the newer Microsoft Graph API as well,
POST https://graph.microsoft.com/beta/applications
but the ability to create applications is still in beta and hence not recommeded for production workloads. So even though Microsoft Graph API would be recommende for most scenarios, at least for this one, using Azure AD Graph API is the way to go currently.
I have covered this in a little more detail in a similar SO Post here.

Categories