Angular app stops receive an exception after publish - c#

Here is a basic Asp net core application with angular 8, created from a visual studio's 2019 template.
Could someone explain
why when I receive an error from API and throw an exception at client's backend during debug session via Visual studio, method in component.ts receive that exception successfully.
But, after publish the app (publish to folder via VS2019, then copy files to IIS and convert to app)
, there is just a 500 error, but according log file my exception was throw.
component.ts has a method
createRelatedTask() {
if (this.validation()) {
this.taskService.createRelatedTask(this.relatedTask).subscribe(
result => {
this.router.navigate(['/home']);
},
error => {
this.showMessage(error.error, error.message);
});
}
}
taskService.ts has a method
createRelatedTask(relatedTask: RelatedTaskData) {
return this.http.post<RelatedTaskData>(this._baseUrl + 'TaskService/', relatedTask);
}
TaskServiceController
[HttpPost]
public async Task<RelatedTaskInfo> CreateRelatedTask(RelatedTaskInfo relatedTask)
{
var result = await _taskService.CreateRelatedTaskAsync(relatedTask);
return result;
}
TaskService
public async Task<RelatedTaskInfo> CreateRelatedTaskAsync(RelatedTaskInfo relatedTask)
{
using (var httpClient = new HttpClient())
{
var apiClient = new RelatedTaskClient(httpClient) { BaseUrl = _relatedTaskApiSettings.ApiAddress };
var dto = Map(relatedTask);
try
{
var response = await apiClient.CreateRelatedTaskAsync(dto);
var result = Map(response);
return result;
}
catch (ApiException e)
{
var text = System.Text.RegularExpressions.Regex.Unescape(e.Response);
throw new Exception(text);
}
catch
{
throw;
}
}
}
while running via VisualStudio
when published to IIS

Related

Asp.Net Core Web API returns the result while client is hanging

I have a simple Asp.Net Core Web API with .NET 6, running on IIS 10, Windows 10. The web API calls another API and returns the results. Below is a simplified version of its code but I tried to keep the most important parts.
[ApiController]
[Produces("application/json")]
public class SomeController
{
private async Task<ApiOutput> RunApiForClientAsync(ApiInput input)
{
try
{
//create a httpclient with a lot of configuration
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
return new ApiOutput
{
Data = content,
Error = null,
StatusCode = 200,
Input = input,
};
}
catch(Exception ex)
{
return new ApiOutput
{
Data = null,
Error = new ApiError("Error Getting the Result from the Server", ex.Message),
StatusCode = 400,
Input = input,
};
}
}
private async Task<List<ApiOutput>> RunApiCallsAsync(string requestId, IEnumerable<ApiInput> items)
{
var result = new List<ApiOutput>();
var tasks = new List<Task<ApiOutput>>();
foreach(var item in items)
{
tasks.Add(RunApiForAsync(item));
}
var taskResults = await Task.WhenAll(tasks);
result.AddRange(taskResults);
return result;
}
[HttpPost]
[Route("rest/multiple")]
public async Task<IActionResult> PostMultiple(ApiInput[] models, string? requestId)
{
_logger.LogInformation(ApiLoggingEvents.PostMultiple, "Request received with ID {requestId}", requestId);
var result = await RunApiCallsAsync(requestId, models);
try
{
_logger.LogDebug(ApiLoggingEvents.PostMultiple, "Request ID {requestId} Generating JSONs.", requestId);
var resultJson = GetJson(result);
await SaveResultAsync(resultJson, requestId);
_logger.LogDebug(ApiLoggingEvents.PostMultiple, "Request ID {requestId} Everything is finished. Returning....", requestId);
return Content(resultJson, "application/json");
}
catch (Exception ex)
{
_logger.LogDebug(ApiLoggingEvents.PostMultiple, "Exception while returning {requestId}, message {msg}", requestId, ex.Message);
throw new Exception("Try again");
}
}
}
Every once in a while, the caller sends the request to the API but never gets the result back. However, when I read the logs, I see the last line for the request is the line containing the text "Everything is finished. Returning" which means everything was successful. In addition, the output JSON is saved on the server's local drive (the await SaveResultAsync(resultJson, requestId); call is successful too).
I should mention that these types of requests are the ones that take a long while to respond. Usually around 10 minutes. Is there a setting that I need to change on the application or the IIS?
I tried to use the following but it doesn't work with the In-Process model:
builder.WebHost.UseKestrel(o =>
{
o.Limits.MaxConcurrentConnections = 100;
o.Limits.KeepAliveTimeout = TimeSpan.FromMilliseconds(timeout);
o.Limits.MaxRequestBodySize = int.MaxValue;
o.Limits.MaxResponseBufferSize = int.MaxValue;
});
Note:
The requestId is a unique GUID for every request to help me keep track of each request on the log file and see whether it was successful or not and if it has created the output file.
Update:
Upon further investigation, it seems like the requests that have a runtime more than 5 minutes are failing. Any idea what might be related to this number?
Update 2:
I created a very simple endpoint that waits for a specified amount of seconds, then returns back with a simple message:
[HttpPost]
[Route("rest/testpost")]
public IActionResult TestPost(int delay)
{
_logger.LogInformation(1, "Delay for {delay} started.", delay);
Thread.Sleep(delay * 1000);
_logger.LogInformation(1, "Delay for {delay} ended.", delay);
return Ok($"Delay for {delay} worked.");
}
I then added the requestTimeout="00:20:00" to the web.config file, just to make sure.
Interestingly, for values such as 310 seconds, sometimes I get the result, but sometimes I don't. (Postman still hangs)
To your web.config, add the following (the value is in seconds--so this will allow runtimes up to 20 minutes):
<system.web>
<httpRuntime executionTimeout="1200" />
</system.web>
Here is a link to the documentation: https://learn.microsoft.com/en-us/dotnet/api/system.web.configuration.httpruntimesection.executiontimeout?view=netframework-4.8

UWP App deployment with C# and REST

I want to deploy and install an .appxbundle with c# on a UWP(IoT) - Device.
The REST-API documentation is on this site.
My code is
public async static Task<bool> UploadApp(string ip, Stream upload, string fileName)
{
try
{
if (http == null)
GetHttp();
HttpContent content = new StreamContent(upload);
var param = new Dictionary<string, string> {
{ "package", fileName}
};
var urlparam = new FormUrlEncodedContent(param);
var urlVar = await urlparam.ReadAsStringAsync();
var response = await http.PostAsync(String.Format("http://{0}:8080/api/app/packagemanager/package?{1}", ip, urlVar), content);
return response.IsSuccessStatusCode;
}
catch
{
return false;
}
}
The code is not working. I get an "Bad request" Error after I send it and I don't know what to change. Could someone help me?
EDIT: The message I get is "Missing .appx (or .eappx) or .appinstaller file in uploaded files". I can deploy and install the package with ARC as "multipart/form-data".

View not found due to await GetAsync

The view 'Search' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Search.aspx
~/Views/Home/Search.ascx
~/Views/Shared/Search.aspx
~/Views/Shared/Search.ascx
~/Views/Home/Search.cshtml
~/Views/Home/Search.vbhtml
~/Views/Shared/Search.cshtml
~/Views/Shared/Search.vbhtml
I am working on a basic web application that reads data from an api. When I run the solution and try to access the view referenced by this controller from the code below, I get this error. I have narrowed it down to being the GetAsync line of code. This works on windows however does not work on my Mac.
From what I can find, the cross platform .net framework Mono, used by visual studio on OSX, does not support GetAsync. What are my options if I want to develop/test this on my Mac but also deploy on a azure server?
public async Task<ActionResult> Search(string ticker)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(demoapiurl);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
try
{
HttpResponseMessage res = await client.GetAsync(string.Format("{0}&symbol={1}&apikey={2}", apiurl, ticker, apikey));
if (res.IsSuccessStatusCode)
{
var accResponse = res.Content.ReadAsStringAsync().Result;
var quotes = GettingStarted.FromJson(accResponse);
GettingStarted allquotes = JsonConvert.DeserializeObject<GettingStarted>(accResponse);
return View(allquotes);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception Message: " + ex.Message);
}
}
return View();
}

GetAsync azure call no result

Using VS 2017 Community. Azure.
I have Azure setup, I have a blank webapp created just for test purpose.
My actual site is an Angular2 MVC5 site, currently run locally.
The following is the code that should... Contact azure providing secret key(the site is registered in azure Active directory).
From this i get a token i then can use to contact azure api and get list of sites.
WARNING: code is all Sausage code/prototype.
Controller
public ActionResult Index()
{
try
{
MainAsync().ConfigureAwait(false);
}
catch (Exception e)
{
Console.WriteLine(e.GetBaseException().Message);
}
return View();
}
static async System.Threading.Tasks.Task MainAsync()
{
string tenantId = ConfigurationManager.AppSettings["AzureTenantId"];
string clientId = ConfigurationManager.AppSettings["AzureClientId"];
string clientSecret = ConfigurationManager.AppSettings["AzureClientSecret"];
string token = await AuthenticationHelpers.AcquireTokenBySPN(tenantId, clientId, clientSecret).ConfigureAwait(false);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
client.BaseAddress = new Uri("https://management.azure.com/");
await MakeARMRequests(client);
}
}
static async System.Threading.Tasks.Task MakeARMRequests(HttpClient client)
{
const string ResourceGroup = "ProtoTSresGrp1";
// Create the resource group
// List the Web Apps and their host names
using (var response = await client.GetAsync(
$"/subscriptions/{Subscription}/resourceGroups/{ResourceGroup}/providers/Microsoft.Web/sites?api-version=2015-08-01"))
{
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsAsync<dynamic>().ConfigureAwait(false);
foreach (var app in json.value)
{
Console.WriteLine(app.name);
foreach (var hostname in app.properties.enabledHostNames)
{
Console.WriteLine(" " + hostname);
}
}
}
}
Controller class uses a static helper class that gets the token from Azure...
public static class AuthenticationHelpers
{
const string ARMResource = "https://management.core.windows.net/";
const string TokenEndpoint = "https://login.windows.net/{0}/oauth2/token";
const string SPNPayload = "resource={0}&client_id={1}&grant_type=client_credentials&client_secret={2}";
public static async Task<string> AcquireTokenBySPN(string tenantId, string clientId, string clientSecret)
{
var payload = String.Format(SPNPayload,
WebUtility.UrlEncode(ARMResource),
WebUtility.UrlEncode(clientId),
WebUtility.UrlEncode(clientSecret));
var body = await HttpPost(tenantId, payload).ConfigureAwait(false);
return body.access_token;
}
static async Task<dynamic> HttpPost(string tenantId, string payload)
{
using (var client = new HttpClient())
{
var address = String.Format(TokenEndpoint, tenantId);
var content = new StringContent(payload, Encoding.UTF8, "application/x-www-form-urlencoded");
using (var response = await client.PostAsync(address, content).ConfigureAwait(false))
{
if (!response.IsSuccessStatusCode)
{
Console.WriteLine("Status: {0}", response.StatusCode);
Console.WriteLine("Content: {0}", await response.Content.ReadAsStringAsync());
}
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsAsync<dynamic>().ConfigureAwait(false);
}
}
}
}
ISSUE:
Ok so the issue I was faced with was Async Deadlocks in my code. So i looked at this stack post stack post here
I fixed the issues by putting in .ConfigureAwait(false) on most of the await declarations.
Code runs and gets all the way back to the controller with a token etc and runs through the MakeARMRequests(HttpClient client) method, however the json only returns 1 result "{[]}" when i debug and as such ignores the loops.
My question is, is my code the culprit here? or would this point to a configuration setting in azure?
Not sure if this is the issue you are facing now BUT you never wait for a result from your async action in the first method Index in your code. MainAsync().ConfigureAwait(false); will immediately return and continue to the next block while the task MainAsync() will start in the background. The catch handler also does nothing because you dont wait f or a result.
Option 1 (recommended)
public async Task<ActionResult> Index()
{
try
{
await MainAsync().ConfigureAwait(false);
}
catch (Exception e)
{
Console.WriteLine(e.GetBaseException().Message);
}
return View();
}
Option 2 if you can't use async/await for some reason
public ActionResult Index()
{
try
{
MainAsync().GetAwaiter().GetResult();
}
catch (Exception e)
{
Console.WriteLine(e.GetBaseException().Message);
}
return View();
}
The Code looks OK and runs fine, Anyone who could help verify would be good, but one can assume this is OK.
The issue for this was configuration in azure, When you register an app you must set a certain number of Access controls via the subscription.
In this case I set some more specific things for the web api , for now set the app as owner and made reference to service management api.
Probably don't need half the "IAM" added in the subscription to the registered app, I simply went through adding the relevant ones and debugging each time until finally i got the results expected.

C# Getting result status when deploing Azure Virtual Machine using Azure Resource Manager(ARM)

I'd like to get result of azure vm deployment using Azure Resource Manager(ARM) with .NET C# to recognize its success or fail.
I found following sample.
https://learn.microsoft.com/en-us/azure/virtual-machines/virtual-machines-windows-csharp-template
In this article, when deploing, "return await" statement is used.
public static async Task<DeploymentExtended> CreateTemplateDeploymentAsync(
TokenCredentials credential,
string groupName,
string deploymentName,
string subscriptionId){
Console.WriteLine("Creating the template deployment...");
var deployment = new Deployment();
deployment.Properties = new DeploymentProperties
{
Mode = DeploymentMode.Incremental,
Template = File.ReadAllText("..\\..\\VirtualMachineTemplate.json"),
Parameters = File.ReadAllText("..\\..\\Parameters.json")
};
var resourceManagementClient = new ResourceManagementClient(credential)
{ SubscriptionId = subscriptionId };
return await resourceManagementClient.Deployments.CreateOrUpdateAsync(
groupName,
deploymentName,
deployment);
}
How can I handle the result?
I want to devide program according to the result.
We can get the deployment status using the Properties.ProvisioningState. But when it deploy VM failed, may throw exception, so we need to catch the exception with code.
1.Code demo :
var token = GetAccessTokenAsync();
var credential = new TokenCredentials(token.Result.AccessToken);
string provisoningStatus = "Failed";
try
{
var result =CreateTemplateDeploymentAsync(credential, "tom", "MyWindowsVM", "you subscription Id")
.Result;
provisoningStatus = result.Properties.ProvisioningState;
}
catch (Exception)
{
//ToDo
}
if (provisoningStatus.Equals("Failed"))
{
//TODo
}
}
Create a VM successfully
Check from the Azure Portal
If it is failed without catching exception

Categories