1
votes

I am trying to delete an Azure function from my Function App through C#. But while deleting it programmatically, the function is not seen on the User Interface, but when I check it through Advanced tools (Kudu), I can still see my Azure function.

So basically while deleting the Azure function, what I do is, I delete it's function.json, and by doing so the Azure function isn't visible in Functions App list (see image below)

enter image description here

But when I go to Advanced Kudu to check whether it has been deleted, I can still see it, but without the function.json file. I had done this before (around 6 months back) and back then it was working properly. I don't know if I am doing it wrong or has anything changed.

enter image description here

Any help with the code would be appreciated.

Thanks

Edit:

The details that I have with me is the Function App's username, password, url, name (https://my-function-app.scm.azurewebsites.net/api/vfs/site/wwwroot), and azure function's name.

A little sample code of what I did which worked 6 months back

private WebClient _webClient = new WebClient
        {
            Headers = { ["ContentType"] = "application/json" },               
            Credentials = new NetworkCredential(username, password),
            BaseAddress = functionsSiteRoot,
        };

var functionJson =
          JsonConvert.DeserializeObject<FunctionSettings>(_webClient.DownloadString("MyFunctionName/function.json"));            

        _webClient.Headers["If-Match"] = "*";
        _webClient.UploadString("MyFunctionName/function.json", "DELETE", JsonConvert.SerializeObject(functionJson));
1

1 Answers

2
votes

You could use REST API to perform this operation.

https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/functions/{functionName}?api-version=2016-08-01

Method: DELETE

Code Snippet:

 HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Delete, string.Format("https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/functions/{functionName}?api-version=2016-08-01", "Pass All Param In {}")));

 request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", results.access_token);

 HttpResponseMessage response = await _client.SendAsync(request);
 if (response.IsSuccessStatusCode)
 {
    dynamic objApiResponse = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());

 }
 else
 {
    return req.CreateResponse(HttpStatusCode.OK, "Sorry Invalid Request");
 }

For details please have a look on official docs

Note: For token request your resource/Scope should be https://management.azure.com. Pass your token while send request.

Update:

You can request for token using client_credentials authentication flow. Try below format:

Azure Portal Credentials For App Id and Tenant Id:

enter image description here

Application Secret from Portal:

enter image description here

Token Endpoint Or URL:

https://login.microsoftonline.com/YourTenantName.onmicrosoft.com/oauth2/token

Request Param:

grant_type:client_credentials
client_id:b603c7be_Your_App_ID_e6921e61f925
client_secret:Vxf1Sl_Your_App_Secret_2XDSeZ8wL/Yp8ns4sc=
resource:https://graph.microsoft.com 

PostMan Sample:

enter image description here

Token On Response:

enter image description here

Code Snippet For Token:

            //Token Request End Point
            string tokenUrl = $"https://login.microsoftonline.com/YourTenant/oauth2/token";
            var tokenRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);

            //I am Using client_credentials as It is mostly recomended
            tokenRequest.Content = new FormUrlEncodedContent(new Dictionary<string, string>
            {
                ["grant_type"] = "client_credentials",
                ["client_id"] = "20e08e95-_Your_App_ID_e9c711b0d19e",
                ["client_secret"] = "+trl[ZFl7l_Your_App_Secret__ghon9",
                ["resource"] = "https://management.azure.com/"
            });

            dynamic json;
            AccessTokenClass results = new AccessTokenClass();
            HttpClient client = new HttpClient();

            var tokenResponse = await client.SendAsync(tokenRequest);

            json = await tokenResponse.Content.ReadAsStringAsync();
            results = JsonConvert.DeserializeObject<AccessTokenClass>(json);


            //New Block For Accessing Data from API
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Delete, string.Format("https://management.azure.com/subscriptions/YOurSubscription/resourceGroups/YourResourceGroup/providers/Microsoft.Web/sites/DeleteTestFuncAppName/functions/DeleteFunctionNameThatYouWantToDelete?api-version=2016-08-01"));
            //Passing Token For this Request
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", results.access_token);
            HttpResponseMessage response = await client.SendAsync(request);
            //Read Server Response
            dynamic objServerResponse = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());

Class I Have Used:

   public class AccessTokenClass
        {
            public string token_type { get; set; }
            public string expires_in { get; set; }
            public string resource { get; set; }
            public string scope { get; set; }
            public string access_token { get; set; }
            public string refresh_token { get; set; }

        }

Point To Remember:

If you got this error

InvalidAuthenticationToken: The received access token is not valid: at least one of the claims 'puid' or 'altsecid' or 'oid' should be present. If you are accessing as application please make sure service principal is properly created in the tenant

You have to assign role to your application like below:

enter image description here