1

I have a big MVC project and this is my API controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using AutoMapper;
using Library.Dtos;
using Library.Models;
using System.Data.Entity;

namespace Library.Controllers.Api
{
    public class RentalsController : ApiController
    {
        private ApplicationDbContext _context;

        public RentalsController()
        {
            _context = new ApplicationDbContext();
        }

        // GET /api/rentals
        public IHttpActionResult GetRentals(string query = null)
        {
            var rentalsQuery = _context.Rentals
                .Include(r => r.Customer)
                .Include(r => r.Book);

            var rentalDtos = rentalsQuery
                .ToList()
                .Select(Mapper.Map<Rental, RentalDto>);

            return Ok(rentalDtos);
        }

        // GET /api/rentals/1
        public IHttpActionResult GetRental(int id)
        {
            var rental = _context.Rentals.SingleOrDefault(r => r.Id == id);

            if (rental == null)
                return NotFound();

            return Ok(Mapper.Map<Rental, RentalDto>(rental));
        }


        [HttpDelete]
        public IHttpActionResult DeleteRental(int id)
        {
            var rentalInDb = _context.Rentals.SingleOrDefault(c => c.Id == id);

            if (rentalInDb == null)
                return NotFound();

            var book = _context.Books.Single(c => c.Id == id);

            book.NumberAvailable++;

            _context.Rentals.Remove(rentalInDb);
            _context.SaveChanges();

            return Ok();
        }
    }
}

This is my Controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Web.Http;
using AutoMapper;
using Library.Dtos;
using Library.Models;

namespace Library.Controllers.Api
{
    public class NewRentalsController : ApiController
    {

        private ApplicationDbContext _context;

        public NewRentalsController()
        {
            _context = new ApplicationDbContext();
        }

        [HttpPost]
        public IHttpActionResult CreateNewRentals(NewRentalDto newRental)
        {
            var customer = _context.Customers.Single(c => c.Id == newRental.CustomerId);

            var books = _context.Books.Where(m => newRental.BookIds.Contains(m.Id)).ToList(); //SELECT * FROM Books WHERE Id IN (1,2,3 etc)

            foreach (var book in books)
            {
                if (book.NumberAvailable == 0)
                    return BadRequest("Ksiazka jest niedostepna.");

                book.NumberAvailable--;

                var rental = new Rental
                {
                    Customer = customer,
                    Book = book,
                    DateRented = DateTime.Now
                };

                _context.Rentals.Add(rental);
            }

            _context.SaveChanges();

            return Ok();
        }
    }
}

This is my Index View, where I am executing deleting:

@model IEnumerable<Library.Models.Rental>
@{
    ViewBag.Title = "Wypozyczenia";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Rentals</h2>

<table id="rentals" class="table table-bordered table-hover">
    <thead>
    <tr>
        <th>Klient</th>
        <th>Tytul</th>
        <th>Data wypozyczenia</th>
        <th>Akcje</th>
    </tr>
    </thead>
    <tbody></tbody>
</table>

@section scripts
{
    <script>
        $(document).ready(function () {
            var table = $("#rentals").DataTable({
                ajax: {
                    url: "/api/rentals",
                    dataSrc: ""
                },
                columns: [
                    {
                        data: "Customer.Name"
                    },
                    {
                        data: "Book.Name"
                    },
                    {
                        data: "DateRented"
                    },
                    {
                        data: "Id",
                        render: function (data) {
                            return "<button class='btn-link js-delete' data-rentals-id=" + data + ">Zwrot zamowienia.</button>";
                        }
                    }
                ]
            });

            $("#rentals").on("click", ".js-delete",
                function () {
                    var button = $(this);

                    if (confirm("Na pewno?")) {
                        $.ajax({
                            url: "/api/rentals/" + button.attr("data-rentals-id"),
                            method: "DELETE",
                            success: function () {
                                //datatable methods - row, remove and draw
                                table.row(button.parents("tr")).remove().draw();
                            }
                        });
                    }
                });

        });
    </script>
}   

And, lastly, this is my Rental class (Model):

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace Library.Models
{
    public class Rental
    {
        public int Id { get; set; }

        [Required]
        public Customer Customer { get; set; }

        [Required]
        public Book Book { get; set; }

        public DateTime DateRented { get; set; }

        public DateTime? DateReturned { get; set; }

    }
}

The problem is - I want to DELETE the RENTAL object from my DB, but before doing that, I want to modify value of one of the objects (Book) inside the RENTAL object; I want to increment value "NumberAvailable".

Book class (model):

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace Library.Models
{
    public class Book
    {
        public int Id { get; set; }
        [Required]
        [StringLength(255)]
        public string Name { get; set; }

        public Genre Genre { get; set; }

        [Display(Name = "Kategoria")]
        [Required]
        public byte GenreId { get; set; }

        public DateTime DateAdded { get; set; }

        [Display(Name ="Data publikacji")]
        public DateTime ReleaseDate { get; set; }

        [Display(Name = "Ilosc w magazynie")]
        [Range(1, 40)]
        public byte NumberInStock { get; set; }

        public byte NumberAvailable { get; set; }
    }
}

Is it even possible?

Thanks for any help.

2 Answers 2

1

You're attempting to alter a book using the same id as the rental. Your query for the book should use rentalInDb.Book.Id. That will get you the record you need to modify.

Sign up to request clarification or add additional context in comments.

2 Comments

It doesn't work either : ( Tried it and code simply doesnt execute, thus it compiles w/o any warnings. It couses POST 400 Error.
Are you able to debug? A bad request should tell you why. Is the id not getting parsed from the URL? Also returning Ok without any parameters can be interpreted incorrectly be the js code, I recommend returning Ok(true).
1

Try this:

 book.NumberAvailable++;

 _context.Books.Add(book);
 _contextEntry(book).State = System.Data.Entity.EntityState.Modified;

 _context.Rentals.Remove(rentalInDb);
 _context.SaveChanges();
 return Ok();

You need to add your object to list of modified to persist on your database.

2 Comments

I don't have access to this project now :( But asap I will try your solution.
Okay let me know if it works as reference also to others with the same problem as yours.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.