Robert Laverick
Robert Laverick

Reputation: 21

ASP.NET Web API Put request unable to find method in controller

I am trying to update the value of an album using a web api service, but when I use the put request it gets to the controller (sometimes), creates the context, but is then doesn't find/run the PUT method I have.

I'm sending the class Album (below), formatted as JSON to Web API.

public class Album
{
    [ScaffoldColumn(false)]
    public int Id { get; set; }

    [Required]
    public string Title { get; set; }

    public string Description { get; set; }

    [Required]
    public string Artist { get; set; }

    public string Genre { get; set; }

    [Required]
    public int Year { get; set; }

    [Display(Name="No. Tracks")]
    public int NumberOfTracks { get; set; }
}

This is the WebAPI controller that should be receiving it all

public class AlbumsController : ApiController
{
    private AlbumsContext db = new AlbumsContext();

    // GET api/Albums

    public IQueryable<Album> Get()
    {
        return (from a in db.Albums select a);
    }

    public IQueryable<Album> Get(int skip, int page)
    {
        var ret = (from a in db.Albums select a);
        ret = ret.OrderBy(a => a.Title);
        ret = ret.Skip(skip);
        ret = ret.Take(page);
        return ret;
    }

    // GET api/Albums/5
    public Album Get(int id)
    {
        return db.Albums.FirstOrDefault(a => a.Id == id);
    }

    // PUT api/Albums
    [HttpPut]
    public HttpResponseMessage Put([FromBody]Album album)
    {
        if (!ModelState.IsValid)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        }

        db.Entry(album).State = EntityState.Modified;

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
        }

        return Request.CreateResponse(HttpStatusCode.OK);
    }

    // POST api/Albums
    public HttpResponseMessage Post(Album album)
    {
        if (ModelState.IsValid)
        {
            db.Albums.Add(album);
            db.SaveChanges();

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, album);
            response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = album.Id }));
            return response;
        }
        else
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        }
    }

    // DELETE api/Albums/5
    public HttpResponseMessage Delete(int id)
    {
        Album album = db.Albums.Find(id);
        if (album == null)
        {
            return Request.CreateResponse(HttpStatusCode.NotFound);
        }

        db.Albums.Remove(album);

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
        }

        return Request.CreateResponse(HttpStatusCode.OK, album);
    }

    protected override void Dispose(bool disposing)
    {
        db.Dispose();
        base.Dispose(disposing);
    }
}

And this is the Server controller method making the PUT request

[HttpPut]
public ActionResult Edit(Album album, HttpPostedFileBase Image1, HttpPostedFileBase Image2, HttpPostedFileBase Image3, int AlbumID, int RemoveID = 0)
{
    string AlbumApiUri = "http://localhost:58431/api/Albums";

    HttpRequestMessage request = new HttpRequestMessage();

    request.RequestUri = new Uri(AlbumApiUri);

    request.Method = HttpMethod.Put;

    MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();

    request.Content = new ObjectContent<Album>(album, jsonFormatter);

    request.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");

    album.Id = AlbumID;

    HttpClient client = new HttpClient();

    var response = client.SendAsync(request).Result;

    if (response.IsSuccessStatusCode)
    {
        bool a = true;
    }
    else
    {
        bool b = true;
    }

    return RedirectToAction("Details", new { ID = AlbumID });
}

Upvotes: 0

Views: 1024

Answers (1)

Robert Laverick
Robert Laverick

Reputation: 21

It turns out I'm pretty much an idiot, the major reason this was kicking off issues was that I hadn't marked Album as a DataContract and include DataMember fields. Hopefully this'll teach anyone who makes the same mistake!

Upvotes: 2

Related Questions