Getting 'TypeError: Failed to fetch' error when trying to call AspNetCore Restful API from Blazor Wasm - asp.net-core

I'm getting a 'TypeError: Failed to fetch' error when trying to call my AspNetCore Restful API from Blazor Wasm. I can call it from Postman, and it works fine.
My Environment:
Microsoft Visual Studio Community 2019 Preview Version 16.6.0 Preview 3.0
Client: Blazor Wasm Service (dotnetstandard 2.1)
AspNet.WebApi.Client 5.2.7
AspNetCore..WebAssembly 3.2 preview 4.2
System.Net.Http.Json 3.2 preview 5.2
Important Usings:
using Microsoft.AspNetCore.JsonPatch;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
Parent namespace and class omitted
_httpClient is injected into parent class
public async Task<MyDto> UpdatePartialAsync(Guid primaryId, ObjectForUpdateDto objectForUpdateDto)
{
MyDto dtoFromApi = null;
var patchDoc = new JsonPatchDocument<ObjectForUpdateDto>()
.Replace(o => o.Name, objectForUpdateDto.Name)
.Replace(o => o.Description, objectForUpdateDto.Description)
var uri = $"MyUri/myResources/{primaryId}";
try
{
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var serializedPatchDoc = JsonConvert.SerializeObject(patchDoc);
var json = new StringContent(serializedPatchDoc, Encoding.UTF8, "application/json-patch+json");
var response = await _httpClient.PatchAsync(uri, json);
return await response.Content.ReadAsAsync<MyDto>();
}
catch (Exception)
{
throw; //throws 'TypeError: Failed to fetch'
}
return dtoFromApi;
}
My API (.Net 5.0, also tried .Net Core 3.1):
[HttpPatch]
[Route("{primaryId}")]
public ActionResult UpsertPartial([FromRoute]Guid primaryId, [FromBody] JsonPatchDocument<ObjectForUpdateDto> objectForUpdateDto)
{
//client call never makes it here
return NoContent();
}

What a misleading error message. It was a CORS issue.
The fix was adding "PATCH" to my CORS policy in my API's startup.cs ConfigureServices method (which previously was "GET, DELETE, PUT, POST, OPTIONS").
services.AddCors(options =>
{
options.AddPolicy(CorsAllowAll,
builder =>
{
builder.WithOrigins(Constants.ApiClientCors).AllowAnyHeader().WithMethods("GET, PATCH, DELETE, PUT, POST, OPTIONS");
});
});

#inliner49er, I wish that I could add a comment to clarify what you responded, since your answer is correct, but I don't have enough reputation points. Therefore, I'll post my tweaks to your answer as a separate answer.
You nailed it, the CORS issue fixed my program also. The only part of your code that didn't make sense was the reference that you have to a class called Constants. I am in the process of trying to complete the PluralSight tutorial, and because I'm working entirely internally, I can safely replace your code with the following:
services.AddCors(options =>
{
options.AddPolicy("PolicyName", builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
I am super new to all of this, literally hours into the process of learning about it, so there is a buttload that I don't understand. I just thought I'd post this to help anyone who might have similar questions to what I had.

You can also try adding these lines directly to the Configure method of the Startup class:
//ENABLE CORS
app.UseCors(x => x
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed(origin => true) // allow any origin
.AllowCredentials()); // allow credentials

Related

NewtonsoftJsonInputFormatter is not available as InputFormatter in .NET5

I have NET5 application and in statup I have configured the application to use Newtonsoft instead of System.Text.Json. For posting CSP report I want to add application/csp-report as a supported media type.
Even though I have configured to use Newtonsoft using AddNewtonsoftJson, the NewtonsoftJsonInputFormatter is still not available as inputformatter. The following code returns null
when try to find in InputFormatters collection.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(config =>
{
var jsonInputFormatter = options.InputFormatters
.OfType<NewtonsoftJsonInputFormatter>()
.First();
//jsonInputFormatter is null here
jsonInputFormatter.SupportedMediaTypes.Add("application/csp-report")
})
// Use Newtonsoft’s Json.NET instead of System.Text.Json.
.AddNewtonsoftJson((options)=>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
})
}
based on the post here . The accepted answer in that post did not work for me. However the other suggested work around by #Vincent Rutten did work
services.AddOptions<MvcOptions>()
.PostConfigure<IOptions<JsonOptions>, IOptions<MvcNewtonsoftJsonOptions>, ArrayPool<char>, ObjectPoolProvider, ILoggerFactory>(
(mvcOptions, jsonOpts, newtonJsonOpts, charPool, objectPoolProvider, loggerFactory) =>
{
var formatter = mvcOptions.InputFormatters.OfType<NewtonsoftJsonInputFormatter>().First(i => i.SupportedMediaTypes.Contains("application/json"));
formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/csp-report"));
mvcOptions.InputFormatters.RemoveType<NewtonsoftJsonInputFormatter>();
mvcOptions.InputFormatters.Add(formatter);
});

Specific API call is getting stalled in chrome with .net core 3.1

I am developing a application using .Net core 3.1 and Angular 8. Every thing is fine with the application except one API call. The API call is of type GET and only that API call is getting stalled. I am not able to find the reason for it as I am calling and utilizing it same as other APIs. And other APIs are working perfectly fine. I have searched for the issue and found that Google Chrome doesn't support more than 6 TCP connections at a time.
I have run the command netstat -aand got this which I am not able to understand
Below is Angular Code :
getAllTrainings(){
this.apiService.get(environment.master_api_url, 'Training/GetAllTrainingDetails')
.subscribe(result => {
if (result) {
this.allTrainings = result;
this.dataSource = new MatTableDataSource<any>(this.allTrainings)
console.log(result, 'getAllTraining');
}
},error=>{
console.log(error, 'error while fetching all trainings')
})
}
Below is .Net Core Code :
[HttpGet("GetAllTrainingDetails")]
public async Task<IActionResult> GetAllTrainings() {
var trainingDetails = await _trainingService.GetAllAsync();
return Ok(_mapper.Map<List<AllTrainingsDto>>(trainingDetails));
}
While debugging I found the issue:
public async Task<List<TrainingDetail>> GetAllAsync() {
return await _dbSet
.Include(x=> x.ParticipantDetail)
.Include(x=> x.Trainer)
.Include(x=> x.Program)
.Include(x => x.ParticipantDetail)
.ThenInclude(x => x.Participant)
.ToListAsync();
}
Does any one find something wrong with code which can be the reason for this specific API call getting stalled.

405 Response on post using axios in Vue 3.0 app to .Net Core 2.2 with AllowAnyMethod in policy

I am losing my mind and having read a lot of blogs, SO questions and documents I am sure it is a simple fix that I am now completely blind to.
I have an axios post call from a vuejs app to a .net core 2.2 api project. Following the Enable CORS guide from Microsoft I have used Access Policy in Services and decorated the controller. See the code below.
The pre-flight options response is 204 with a 405 response on the actual call citing allow: DELETE, GET, PUT as the permitted method ... what have I missed here? I have .AllowAnyMethod in the policy but it seems to be completely ignored. A colleague working with a WebAPI 2.2. project has the exact same code and it works.
StartUp.cs
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.WithOrigins("http://example.com",
"http://www.contoso.com");
});
options.AddPolicy("VueFrontEnd",
builder =>
{
builder.WithOrigins("http://localhost:30001/")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
Controller
[EnableCors("VueFrontEnd")]
[HttpPost]
public async Task<JsonResult> DoesItExist(string searchString)
{
var data = new string[] { "A", "B", "C" };
var result = data.Any(searchString.Contains);
return Json(JsonConvert.SerializeObject(result));
}
Vue
getClientsByPartialString(search: string) {
Axios({
method: 'post',
url: 'https://localhost:44380/api/values/DoesItExist',
crossDomain: true,
data: {
name: 'world',
},
})
}
This makes me sad. It was routing.
Adding [HttpPost("/TheApi")] decorator sorted it.
I am ashamed. I was using the full URL http://localhost:port/api/values/themethod and routing was failing me despite it being set on the controller.
The one thing that concerns me is why this worked with GET and PUT and ONLY failed on POST. I have no answer to that one.

Integrate swashbuckle swagger with odata in ASP.Net Core [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have tried to implement both ( swagger and odata ) in asp.net core, but it's not working.
I'm unable to integrate the route given for odata.
I have the following Configuration and I receive a generic error.
This is the error
We ran into the same issue when adding OData to our .Net Core project. The workarounds shown in the code snippet on this post fixed our API error(s) when Swagger UI loads.
As far as I can tell, OData isn't supported in Swashbuckle for AspNetCore. So after adding the workaround code in the link above, our Swagger UI works, but none of the OData endpoints show.
Code snippet from the link:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddOData();
// Workaround: https://github.com/OData/WebApi/issues/1177
services.AddMvcCore(options =>
{
foreach (var outputFormatter in options.OutputFormatters.OfType<ODataOutputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0))
{
outputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata"));
}
foreach (var inputFormatter in options.InputFormatters.OfType<ODataInputFormatter>().Where(_ => _.SupportedMediaTypes.Count == 0))
{
inputFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/prs.odatatestxx-odata"));
}
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var builder = new ODataConventionModelBuilder(app.ApplicationServices);
builder.EntitySet<Product>("Products");
app.UseMvc(routebuilder =>
{
routebuilder.MapODataServiceRoute("ODataRoute", "odata", builder.GetEdmModel());
// Workaround: https://github.com/OData/WebApi/issues/1175
routes.EnableDependencyInjection();
});
}
}
I was able to do this using a DocumentFilter. Create a class like the example below, then add it to your Swagger configuration as:
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Info { Title = "Your title API v1.0", Version = "v1.0" });
options.DocumentFilter<CustomDocumentFilter>();
});
Github Example
You can integrate Swagger a couple of different ways. For barebones support, you can use the ODataSwaggerConverter provided by OData. This will effectively convert the EDM to a Swagger document. To wire this up to a Swagger generator library like Swashbuckle, you just need create and register a custom generator. The UI and client side of things should remain unchanged. If the generated Swagger document isn't sufficient, the base implementation of the ODataSwaggerConverter is still a reasonable start.
If you're using API Versioning for OData with ASP.NET Core, you need only add the corresponding API Explorer package. Swashuckle will light up with little-to-no additional work on your part. The ASP.NET Core with OData Swagger sample application has an end-to-end working example.

Swashbuckle/Swagger on .NET Core 2.1 has stopped working since upgrade

I have a .NET Core 2.0 application, using Swashbuckle/Swagger to generate API documentation. When we were on 2.1.0-preview, Swagger was working fine. Then we did the big upgrade to 2.1.0 release and SDK 2.1.300. We didn't notice exactly when things broke, but now our Swagger docs won't load. Here's what we see:
Project has a reference to Swashbuckle.AspNetCore version 2.5.0. The relevant code in Startup.cs is below. In ConfigureServices():
services.AddSwaggerGen(swaggerOptions =>
{
// Register a swagger doc
swaggerOptions.SwaggerDoc("v1", new Info
{
// Optional descriptive info that will be included in the Swagger output
Contact = new Contact
{
Name = "LightSail",
Url = "https://myurl.com/"
},
Description = "A description of the API can go here",
Title = "My API",
Version = "v1"
});
// Xml file to get comment information from
swaggerOptions.IncludeXmlComments("App_Data/Api.xml");
});
And in Configure():
app.UseSwagger();
app.UseSwaggerUI(swaggerUiOptions => swaggerUiOptions.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1"));
I found lots of other similar questions, one of which suggested that there might be duplicate endpoints; I tried adding a call to .ResolveConflictingEndpoints() but that made no difference. I have searched through my project folders and there is no file called swagger.json, so I'm guessing that's the problem.
Any ideas why this is not working, or how to fix?
This is usually indicative of controllers/actions that Swashbuckle doesn't support for one reason or another.
It's expected that you don't have a swagger.json file in your project. Swashbuckle creates and serves that dynamically using ASP.NET Core's ApiExplorer APIs. What's probably happening here is that Swashbuckle is unable to generate Swagger.json and, therefore, the UI is failing to display.
As HelderSepu said, it's hard to know exactly what caused the failure, so the best way to debug is probably just to remove half your controllers (just move the files to a temporary location) and check whether the issues persists. Then you'll know which half of your controllers contains the troublesome action. You can 'binary search' removing controllers (and then actions) until you figure out which action method is causing Swashbuckle to not be able to generate Swagger.json. Once you know that, it should be obvious whether this is some issue in your code or an issue that should be filed in the Swashbuckle repo.
For example, Swashbuckle appears to not support open generics, so having a response type attribute like [ResponseType(typeof(IEnumerable<>))] could cause this sort of behavior. It could also be an issue with ambiguous routes or something like that tripping Swashbuckle up. Once you've narrowed down the cause of failure to something more specific like that, it can either be fixed or filed, as appropriate.
Today I found out that I could just go to the json url in the browser and get some error information
for example
myapiurl/api/vi/swagger.json
I was able to solve this error by explicitly adding the http verb attribute to my asp.net core 2.x controller method. The convention of prefixing the method name with the http verb is not enough for Swashbuckle apparently.
[HttpPost]
public async Task<IActionResult> AddNewData([FromBody] MyType myType) { … }
In my case I can reproduce your error by omitting "." from the end point as you have done.
I don't get the error if I include "." at the start of the path.
Here is more of my code in case it is relevant.
In ConfigureServices I have
services.AddSwaggerGen(c =>
{
c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
c.SwaggerDoc("v1", new Info
{
Version = "v1",
Title = "My API",
Description = "ASP.NET Core Web API",
TermsOfService = "None",
Contact = new Contact
{
Name = "my name",
Email = "me#myemail.com"
}
});
});
In configure
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRewriter(new RewriteOptions()
.AddRedirectToHttpsPermanent());
app.UseSwagger(c =>
{
c.RouteTemplate =
"api-docs/{documentName}/swagger.json";
});
app.UseSwaggerUI(c =>
{
//Include virtual directory if site is configured so
c.RoutePrefix = "api-docs";
c.SwaggerEndpoint("./v1/swagger.json", "Api v1");
});
app.UseMvc(routes =>
{
routes.MapRoute(
"default",
"{controller=Home}/{action=Index}/{id?}");
});
Also there is
public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
if (isAuthorized && !allowAnonymous)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
operation.Parameters.Add(new NonBodyParameter
{
Name = "Authorization",
In = "header",
Description = "access token",
Required = true,
Type = "string"
});
}
}
My dependencies are
Microsoft.AspNetCore.App (2.1.0)
Swashbuckle.AspNetCore (2.5.0)
Microsoft.NETCore.App (2.1.0)
Personally I was a bit quick and forgot to add this line to the method ConfigureServices in Startup.cs.
services.AddSwaggerDocument();
In my case, I missed the 'HttpAttribute':
public async Task<IEnumerable<ClientesListDto>> GetAll()
{
return await _service.GetAllAsync();
}
Then I put it and swagger likes it:
[HttpGet]
public async Task<IEnumerable<ClientesListDto>> GetAll()
{
return await _service.GetAllAsync();
}
In my case, I had this:
[HttpGet("CleanUpSnoozedLeads")]
public async Task<ActionResult<bool>> CleanUpSnoozedLeads()
[HttpGet("CleanUpSnoozedLeads")]
public async Task<ActionResult<bool>> DoSomethingElse()
Notice the HttpGet() had the same name. That causes the undefined error as well.
A very common case is ambiguity. Just use the same signature for two PUT or POST operations for example and you will get the error.
Others answers did not worked for me.
I was able to fix and understand my issue when I tried to go to the swagger.json URL location:
https://localhost:XXXXX/swagger/v1/swagger.json
The page will show the error and reason why it is not found.
In my case, I saw that there was a misconfigured XML definition of one of my methods based on the error it returned:
NotSupportedException: HTTP method "GET" & path "api/Values/{id}" overloaded by actions - ...
...
...
In my case, i just forgot to add the HttpPostAttribute annotation to the method.
[HttpPost]
public ActionResult Post()
{
return Ok();
}
In my case there was a conflict in the schemaId. Apparently every class in the swagger JSON must have a unique schemaId. If you have two classes in different namespaces with the same name this will not work. We have to configure "UseFullTypeNameInSchemaIds" in the startup class.
Add "options.CustomSchemaIds(x => x.FullName);" in "services.AddSwaggerGen"
I found the trace by enabling Output window in VS, selecting the main project from Show output from dropdown list then visit http://{yourapiendpoint}/swagger/v1/swagger.json
If your api have same two or more [HttpGet] its not working swagger.
You should be specify [HttpGet] , [HttpGet ("{id}")]
simple solution