locked
Post and Delete Methods 401 Unauthorized. RRS feed

  • Question

  • User-2132497554 posted

    Hi Folks, 

    I am using Asp.net core with windows authentication in web API and angular. I have created two projects. one is for Backend (10.11.22.215:5200) and other is for Frontend (10.11.22.215:4200). Where 10.11.22.215 is my IP address machine. So I run both projects from Visual Studio 2017 and got all data values list, add new user like Post and Delete user by ID etc etc. It seems fine and there is no error.

    Now I already published both projects to IIS for local network and I run 10.11.22.215:4200 from Chrome browser. I got all data values list and it seems good but I add new user or delete user by Id.  I got error messages and it says: 
    http://10.11.22.215:5200/api/user 401 (Unauthorized) <<--- For Post 

    http://10.11.22.215:5200/api/user/42 401 (Unauthorized) <<---For Delete 

    In Startup.cs (Backend Project):

    public void ConfigureServices(IServiceCollection services)
    {
      // Enable Cross-Origin Request
      services.AddCors(options =>
      {
        options.AddPolicy("CorsPolicy", builder =>
          {
            builder.WithOrigins("http://10.11.22.215:4200", "http://localhost:4200")
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials();
                    });
                });
    
      .......
      .......
    }
    
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    .......
    .......
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseCors("CorsPolicy");
    app.UseAuthentication();
    app.UseMvc();
    }

     In UserController.cs (Backend Project):

        [EnableCors("CorsPolicy")]
        [Route("api/[controller]")]
        [ApiController]
        public class UserController : ControllerBase
        {   
            ....
            ....
     
            #region POST: api/User
            [HttpPost]
            public async Task<ActionResult<User>> PostUser(User user)
            {
                _context.Users.Add(user);
                await _context.SaveChangesAsync();
    
                return CreatedAtAction("GetUser", new { id = user.UserId }, user);
            }
            #endregion
    
            #region DELETE: api/User/5
            [HttpDelete("{id}")]
            public async Task<ActionResult<User>> DeleteUser(int id)
            {
                var user = await _context.Users.FindAsync(id);
                if (user == null)
                {
                    return NotFound();
                }
    
                _context.Users.Remove(user);
                await _context.SaveChangesAsync();
    
                return user;
            }
            #endregion
            ....
            ....
       }

    In User Service (FrontEnd):

    ....
    ....
     
    const httpOptions = {
      headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
      withCredentials: true
    };
    
    ....
    ....
    
    export class UserService {
    ....
    ....
    
    addUserHardwareMachine(user: User): Observable<User> {
        return this.http.post<User>(this.userUrl, user, httpOptions)
          .pipe(catchError(this.handleError<User>('addUserHardwareMachine')));
      }
    
    deleteUserHardwareMachine(id: number): Observable<User> { const url = `${this.userUrl}/${id}` return this.http.delete(url, httpOptions) .pipe(catchError(this.handleError<User>(`deleteUserHardwareMachine id=${id}`))); } .... .... }

    How to fix it? Any Idea?

    I am waiting for your response.

    Thanks in Advance.

    Monday, June 17, 2019 5:32 AM

All replies

  • User585649674 posted

    you have not added cors to the middleware pipeline. you need to add app.useCors() in conifgure section. Refer this https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.2

    Monday, June 17, 2019 6:41 AM
  • User-2132497554 posted

    it was added it. See in Startup.cs section as above my post.

    app.UseCors("CorsPolicy");

    Monday, June 17, 2019 7:27 AM
  • User1120430333 posted

    I simply used HTTPPost attribute for delete method. The actual code that did the delete was in the DAL classlib project 

    using DAL;
    using Entities;
    using Microsoft.AspNetCore.Mvc;
    using System.Collections.Generic;
    
    namespace ProgMgmntCore2Api.Controllers
    {
        [Produces("application/json")]
        [Route("api/[controller]")]
        [ApiController]
    
        public class TaskController : ControllerBase, ITaskController
        {
            private readonly IDaoTask _daoTask;
    
            public TaskController(IDaoTask daoTask)
            {
                _daoTask = daoTask;
            }
    
            [HttpGet]
            [Route("GetTaskById")]
            public DtoTask GetTaskById(int id)
            {
                return _daoTask.GetTaskById(id);
            }
    
            [HttpGet]
            [Route("GetTasksByProjId")]
            public List<DtoTask> GetTasksByProjectId(int id)
            {
                return _daoTask.GetTasksByProjectId(id);
            }
    
            [HttpPost]
            [Route("CreateTask")]
            public void CreateTask(DtoTask dto)
            {
                _daoTask.CreateTask(dto);
            }
    
            [HttpPost]
            [Route("UpdateTask")]
            public void UpdateTask(DtoTask dto)
            {
                _daoTask.UpdateTask(dto);
            }
    
            [HttpPost]
            [Route("DeleteTask")]
            public void DeleteTask(DtoId dto)
            {
                _daoTask.DeleteTask(dto.Id);
            }
        }
    }

    Monday, June 17, 2019 8:55 AM
  • User-2132497554 posted

    What does make difference? I do not use DAL classlib project.

    Monday, June 17, 2019 10:10 AM
  • User1120430333 posted

    What does make difference? I do not use DAL classlib project.

     I am not a follower of what's being taught in books and tutorials, the cheese cake that's too sweet, and I believe is seperation of concerns.  

    https://en.wikipedia.org/wiki/Separation_of_concerns

    Even the repository pattern wouldn't hurt as opposed to the Data Access Layer pattern and not doing CRUD directly from the controller.. 

    Monday, June 17, 2019 3:43 PM
  • User-1764593085 posted

    Hi lamGuy84,

    So, you have 401 errors when you publish to IIS and localhost works well? Do you enable both windows authentication and anonymous authentication for your web api in IIS Manager(also check in launchsettings.json)?

    Tuesday, June 18, 2019 6:21 AM
  • User-2132497554 posted

    Hi Xing Zou,

    you have 401 errors when you publish to IIS and localhost works well?
    Yes

    Do you enable both windows authentication and anonymous authentication for your web api in IIS Manager(also check in launchsettings.json)?
    Yes

    Tuesday, June 18, 2019 11:47 AM
  • User-1764593085 posted

    Hi lamGuy84,

    I could not reproduce it...I have the same problem as you only when I disable anonymous authentication, it works when I enable it and restart.

    Could you try below link to enable options header for cors?

    https://stackoverflow.com/questions/42199757/enable-options-header-for-cors-on-net-core-web-api

    Wednesday, June 19, 2019 10:03 AM
  • User-2132497554 posted

    Update:

    I follow this one:
    https://stackoverflow.com/questions/42199757/enable-options-header-for-cors-on-net-core-web-api

        public class OptionsMiddleware
        {
            private readonly RequestDelegate _next;
    
            public OptionsMiddleware(RequestDelegate next)
            {
                _next = next;
            }
    
            private async Task BeginInvoke(HttpContext context)
            {
            
    
                context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { (string)context.Request.Headers["http://10.11.22.215:4200"] });
                context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Accept" });
                context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });
                context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
                context.Response.StatusCode = 200;
                await context.Response.WriteAsync("OK");
    
                if (context.Request.Method != "OPTIONS")
                {
                    await _next.Invoke(context);
                }
    
    
            }
        }
    
        public static class OptionsMiddlewareExtensions
        {
            public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)
            {
                return builder.UseMiddleware<OptionsMiddleware>();
            }
        }
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                app.UseOptions();
                .......
                .......
            }

    I am getting error message from browser and it's says:

    System.InvalidOperationException: No public 'Invoke' or 'InvokeAsync' method found for middleware of type '.....BackEnd.Controllers.OptionsMiddleware'.
       at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass4_0.<UseMiddleware>b__0(RequestDelegate next)
       at Microsoft.AspNetCore.Builder.Internal.ApplicationBuilder.Build()
       at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
    Friday, June 21, 2019 9:44 AM
  • User753101303 posted

    Hi,

    This is really the problem you have? You looked at https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.2 already ?

    BTW you really have to handle them as two separate projects or is this API private to this front end for now ? Unless It does serve some actual purpose I would deploy them on a single web site for now.

    Edit: seems you left out the private Task Invoke method...

    Friday, June 21, 2019 9:57 AM