1

I am developing one application using Angular 8 and ASP.Net Core3.1.

enter image description here

When I am calling all API few are working fine, few are giving 400 error and few of them 404 error.

API giving 400 error :

MODEL DETAILS

public class ServiceOffer
{
   public int Id { get; set; }
   public string ServiceName { get; set; }
   public string ServiceDescription { get; set; }
   public int ServicePrice { get; set; }
   public bool Status { get; set; }
} 

API DETAILS

[Produces("application/json")]
[ApiController]
public class ServiceofferController : ControllerBase
{
    [HttpGet]
    [Route("api/v1/serviceoffer/allservice")]
    public async Task<IActionResult> Index()
    {
        var objService = new ServiceBL();
        var mob = await objService.GetAllServices();
        return Ok(mob);
    }

    [Route("api/v1/serviceoffer/addservices")]
    public async Task<IActionResult> AddServices([FromBody] ServiceOffer objSer)
    {
        var objService = new ServiceBL();
        int flag = await objService.AddServiceOffer(objSer);
        return Ok(flag);
    }       

    [HttpPut]
    [Route("api/v1/serviceoffer/update")]
    public static async Task<int> UpdateUser([FromBody] ServiceOffer objSer)
    {
        var objService = new ServiceBL();
        return await objService.UpdateServiceOffer(objSer);
    }
}

API Working fine : api/v1/serviceoffer/allservice

API giving 400 error: api/v1/serviceoffer/addservices

API Giving 404 error: api/v1/serviceoffer/update

ANGULAR SERVICE

getAllServices(url: string): Observable<IServiceOffer[]> {
return this.http
  .get<IServiceOffer[]>(url)
  .pipe(catchError(this.handleError));
}
getServiceById(url: string, id: number): Observable<IServiceOffer> {
const editUrl = `${url}/${id}`;
// console.log(editUrl);
return this.http
  .get<IServiceOffer>(editUrl)
  .pipe(catchError(this.handleError));
}
 // insert new contact details
 saveService(url: string, cust: IServiceOffer): Observable<any> {
  var Customer = JSON.stringify(cust);
  console.log(url);
  return this.http
  .post(url, Customer, httpOptions)
  .pipe(catchError(this.handleError));
 }
// update contact details
 updateService(url: string, customer: IServiceOffer): Observable<any> {
 //const newurl = `${url}/${id}`;
  return this.http
    .put(url, customer, httpOptions)
    .pipe(catchError(this.handleError));
 }

CONFIG DETAILS

 public class Startup
{
    public IConfiguration Configuration { get; }
    public static string ConnectionString { get; private set; }
    public static Dictionary<string, string> MailSettings { get; private set; }
    public Dictionary<string, string> SmsSettings { get; set; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        ConnectionString = Configuration.GetSection("ConnectionString").GetSection("SalesContext").Value;

        //MailSettings = Configuration.GetSection("SMTP").GetChildren()
        //              .Select(item => new KeyValuePair<string, string>(item.Key, item.Value))
        //              .ToDictionary(x => x.Key, x => x.Value);

        MailSettings = Configuration.GetSection("SMTP").GetChildren().ToDictionary(x => x.Key, x => x.Value);

        services.AddControllersWithViews();
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });

        //services.AddMvc()
        //     .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
        //     .ConfigureApiBehaviorOptions(options =>
        //       {
        //         options.SuppressConsumesConstraintForFormFileParameters = true;
        //         options.SuppressInferBindingSourcesForParameters = true;
        //         options.SuppressModelStateInvalidFilter = true;
        //         options.SuppressMapClientErrors = true;
        //         options.ClientErrorMapping[404].Link = "https://httpstatuses.com/404";
        //     });

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        if (!env.IsDevelopment())
        {
            app.UseSpaStaticFiles();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");
        });

        app.UseSpa(spa =>
        {              

            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }
}

Any one can explain me why I am getting this horrible error?

Thanks in Advance.

Nkosi
  • 235,767
  • 35
  • 427
  • 472

2 Answers2

1

For the 400 Bad Request, make sure set 'Content-Type': 'application/json' headers and correct Customer Json data. I have tried your test data and it works(Add [HttpPost] on action is better).

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

const cust = { id: 1, serviceName: "Test", serviceDescription: "Test", servicePrice: "1000", status: true } 

var Customer = JSON.stringify(cust);

this.http
  .post("/api/v1/serviceoffer/addservices", Customer, httpOptions)
  .subscribe(result => {
    alert(result);
  }, error => console.error(error));

For the 404 Not Found, you need to remove the static on the PUT action.

Refer to Can MVC action method be static or extension method?

Update 1/14/2020

Try to use servicePrice: 1000 instead of servicePrice: "1000".

If you don't want to do above changes.For asp.net core 3.1, it uses System.Text.Json for serialization and deserialization.

For using old behavior, you could use Json.NET in an ASP.NET Core 3.1 project by referencing Json.NET support.

1) Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 3.1.0

2) Add services.AddControllersWithViews().AddNewtonsoftJson(); in startup.cs

Ryan
  • 19,118
  • 10
  • 37
  • 53
  • Thanks for your reply. I have noticed that the below mention error making this trouble: "errors":{"$.servicePrice":["The JSON value could not be converted to System.Int32. Path: $.servicePrice | LineNumber: 0 | BytePositionInLine: 78."]}. In Angular I have declared ServicePrice as number and in Backend Service it is Int32. Please help to resolve this issue. – Shiv Shankar Maiti Jan 13 '20 at 13:54
  • 1
    @S. S. Maiti I did not note that you were using asp.net core 3.1.I update my answer. – Ryan Jan 14 '20 at 02:21
0

This issue was with .Net Core 3.0. The inbuild JSON formatter not able to convert from Angular numeric to System.Int32. After going through lot of article I came to know that it is a bug. The solution is to Install Microsoft.AspNetCore.Mvc.NewtonsoftJson package. And add this line Startup.cs services.AddControllers().AddNewtonsoftJson();

It has resolved my issue, now all of my service working fine. Thank to all of you.