0

I'm learning web.api from asp.net. The problem is, my delete and put method not working right now. I think there's something wrong with my code :*

Here's my controller for delete:

    [ResponseType(typeof(Location))]
    public IHttpActionResult DeleteLocation(Guid id)
    {
        Location location = _locationRepository.GetSingle(e => e.Id == id);
        if (location == null)
        {
            return NotFound();
        }

        _locationRepository.Delete(location);


        return Ok(location);
    }

and these are my put:

    [HttpPost]
    [ResponseType(typeof(LocationViewModel))]
    public async Task<IHttpActionResult> PutLocation(Guid id, LocationViewModel location)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (id != location.Id)
        {
            return BadRequest();
        }

        location.Id = id;

        try
        {
            await _locationRepository.EditAsync(location.ToModel());
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!LocationExist(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return StatusCode(HttpStatusCode.NoContent);
    }

This confusing me.. My get and post things works perfectly. I'm using postman to test the method and it said: enter image description here

405 method not allowed.. and I have no idea. And these are my generic repository. maybe something wrong with this too..

public abstract class GenericRepository<C, T> :IGenericRepository<T> where T : class,ISoftDelete where C : DbContext, new()
//public abstract class GenericRepository<T> : IGenericRepository<T> where T : class, ISoftDelete
{
    //protected readonly ShopDiaryProject.EF.ShopDiaryDbContext _entities;

    private C _entities = new C();
    public C Context
    {

        get { return _entities; }
        set { _entities = value; }
    }


    public virtual IQueryable<T> GetAll()
    {
        IQueryable<T> query = _entities.Set<T>().Where(i => i.IsDeleted == false);

        return query;
    }

    public virtual IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
    {

        IQueryable<T> query = _entities.Set<T>().Where(i => i.IsDeleted == false).Where(predicate);
        return query;
    }

    public virtual T GetSingle(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
    {
        T data = _entities.Set<T>().Where(i => i.IsDeleted == false).FirstOrDefault(predicate);
        return data;
    }

    public virtual bool Add(T entity)
    {
        try
        {
            _entities.Set<T>().Add(entity);
            this.Save();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
    }

    public virtual bool AddRange(IEnumerable<T> entity)
    {
        try
        {
            _entities.Set<T>().AddRange(entity);
            this.Save();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
    }

    public virtual bool Delete(T entity)
    {
        try
        {
            entity.IsDeleted = true;
            entity.DeletedDate = DateTime.Now;
            Edit(entity);
            this.Save();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
    }

    public virtual bool Edit(T entity)
    {
        try
        {
            entity.ModifiedDate = DateTime.Now;
            _entities.Entry(entity).State = EntityState.Modified;
            this.Save();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
    }

    public virtual bool Save()
    {
        try
        {
            _entities.SaveChanges();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
    }
    private bool _disposed = false;
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                _entities.Dispose();
            }
        }
        _disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public int Count(Expression<Func<T, bool>> match)
    {
        return _entities.Set<T>().Count(match);
    }

    public async virtual Task<bool> AddAsync(T entity)
    {
        try
        {
            _entities.Set<T>().Add(entity);
            await this.SaveAsync();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
    }

    public async virtual Task<bool> AddRangeAsync(IEnumerable<T> entity)
    {
        try
        {
            _entities.Set<T>().AddRange(entity);
            await this.SaveAsync();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
    }

    public async virtual Task<bool> DeleteAsync(T entity)
    {
        try
        {
            entity.IsDeleted = true;
            entity.DeletedDate = DateTime.Now;
            Edit(entity);
            await this.SaveAsync();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
    }

    public async virtual Task<bool> EditAsync(T entity)
    {
        try
        {
            entity.ModifiedDate = DateTime.Now;
            _entities.Entry(entity).State = EntityState.Modified;
            await this.SaveAsync();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
        //catch (Exception e)
        //{
        //    return false;
        //}
    }

    public async virtual Task<bool> SaveAsync()
    {
        try
        {
            await _entities.SaveChangesAsync();
            return true;
        }
        catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    string message = string.Format("{0}:{1}",
                        validationErrors.Entry.Entity.ToString(),
                        validationError.ErrorMessage);
                }
            }
            return false;
        }
    }

Maybe someone here can help me :) Thanks in advance

Bogdan Sorin
  • 129
  • 3
  • 14
Yeremia Danang
  • 139
  • 1
  • 2
  • 12

4 Answers4

1

can you add [HttpDelete] on your delete method , so it get identified as delete action verb

[HttpDelete]
[ResponseType(typeof(Location))]
public IHttpActionResult DeleteLocation(Guid id)
{
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
  • That is right but .NET also identifies the HTTP verb from the name of the Action, in this case, DeleteLocation should be identified as a valid endpoint accepting DELETE verb. – Ipsit Gaur Mar 14 '18 at 08:27
1

Based on MSDN:

Web API also selects actions based on the HTTP method of the request (GET, POST, etc). By default, Web API looks for a case-insensitive match with the start of the controller method name. For example, a controller method named PutCustomers matches an HTTP PUT request.

You can override this convention by decorating the method with any the following attributes:

  • [HttpDelete]
  • [HttpGet]
  • [HttpHead]
  • [HttpOptions]
  • [HttpPatch]
  • [HttpPost]
  • [HttpPut]

So for your Delete method:

[HttpDelete]
[Route("{id}")]
[ResponseType(typeof(Location))]
public IHttpActionResult DeleteLocation(Guid id)
{
}

And from Postman set method to Delete and url to http://localhost:xxxx/api/Locations/xxxx-xxxx-xxxx-xxxx

For your Put method:

[HttpPut]
[Route("{id}")]
[ResponseType(typeof(LocationViewModel))]
public async Task<IHttpActionResult> PutLocation(Guid id, LocationViewModel location)
{
}

And from Postman set method to Put and url to http://localhost:xxxx/api/Locations/xxxx-xxxx-xxxx-xxxx

junkangli
  • 1,152
  • 7
  • 14
  • Still not working.. http://shopdiary.funcraftstudio.com/api/Locations/97ecf0f5-c177-4844-b467-0caf2cbc11b5 still 405 method not allowed – Yeremia Danang Mar 14 '18 at 06:36
  • Still not working.. http://shopdiary.funcraftstudio.com/api/Locations/97ecf0f5-c177-4844-b467-0caf2cbc11b5 still 405 method not allowed public async Task DeleteLocation(Guid id) << is this thing causing problem? And I use this route for post: http://localhost:8080/api/Locations/PostLocation – Yeremia Danang Mar 14 '18 at 06:56
  • You may need to verify your IIS is configured to accept DELETE method - https://stackoverflow.com/questions/9854602/asp-net-web-api-405-http-verb-used-to-access-this-page-is-not-allowed-how – junkangli Mar 14 '18 at 07:05
1

The reason is Delete at Put verbs are not allowed by IIS or IIS Express by default. So you should replace the tag content to the following content in your web.config file.

<validation validateIntegratedModeConfiguration="false" />
<handlers>
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />

//This will enable all Web API verbose
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

Hope it works.

Kevin Law
  • 814
  • 4
  • 15
1

I removed the webdavModule at web.config . And It works!

<system.webServer>
  <modules>
    <remove name="WebDAVModule" />
  </modules>
  <handlers>
    <remove name="WebDAV" />
  </handlers>
</system.webServer>
Yeremia Danang
  • 139
  • 1
  • 2
  • 12