0

I am attempting to use AngularJS to update some data using the $http.put method. However, I have tried several variations on calling this method and it has repeatedly failed to call the put method in my controller - or, if it does, it creates a new entity rather than updating the old data. Here is my code:

(I know the rest of my api works as post and get work fine for cars)

CarController.cs

    public void Put(int CarId, [FromBody] Car c)
    {
        System.Diagnostics.Debug.WriteLine("CarController.Put() Called");
        c.CarId = CarId;
        if (!_repo.UpdateCar(c) || !_repo.Save())
        {
            throw new HttpResponseException(HttpStatusCode.NotFound);
        }
    }

Repository ("_repo"):

    public bool UpdateCar(Car car)
    {
        if (car == null)
        {
            throw new ArgumentNullException("car");
        }
        int index = _ctx.Cars.ToList().FindIndex(c => c.CarId == car.CarId);
        if (index == -1)
        {
            return false;
        }
        _ctx.Cars.ToList().RemoveAt(index);
        _ctx.Cars.Add(car);
        return true;

    }

AngularJS script:

var _linkPersonAndCar = function(person, car) {
    var deferred = $q.defer();

    alert("_linkPersonAndCar()\nPerson = " + JSON.stringify(person) + "\nCar = " + JSON.stringify(car));

    //Update car
    car.persons.splice(0, 0, person);

    alert("_linkPersonAndCar() attempting put");

    $http.put("/api/cars/"+car.carId, car)
        .then(function ()
        {
            alert("_linkPersonAndCar() - Success!");
            deferred.resolve();
        },
        function ()
        {
            alert("_linkPersonAndCar() - Failure updating car");
            deferred.reject();
        });

    alert("_linkPersonAndCar() - Complete");

    return deferred.promise;
};
9
  • You say that it doesn't call the put method, but when it does, it creates a new entity. Which is it? Commented Jun 6, 2014 at 17:12
  • Between this and your other post, you are putting too much into the question. They both seem to be about (1) using angular to call a controller method and (2) why Entity Framework is inserting an item instead of updating. Debug your code and start isolating these problems into separate questions. Commented Jun 6, 2014 at 17:15
  • The problem is that every approach I have taken has done something different and none do what I want so I was hoping to make sure that I wasn't doing something wrong out of ignorance for this method while my other post is asking if there's some way I haven't tried yet that will work Commented Jun 6, 2014 at 17:20
  • And consider using the $resource service as it will help out with a lot of the boilerplate for calling a REST API. Commented Jun 6, 2014 at 17:21
  • It's impossible to answer your questions because without more information no one can know whether it's a problem with the controller and model binding, the angular setup, or your entity framework code. Commented Jun 6, 2014 at 17:30

2 Answers 2

2

Well, see my comments for advice on breaking up this into separate questions. But I see at least one problem with your EF code:

_ctx.Cars.ToList().RemoveAt(index);

Calling ToList() creates a list disconnected from the provider (EF Context), and creates an in-memory list. You then remove the item from that list, which will not accomplish anything, since you don't use that list in any subsequent code. This will not delete the entity from the database, which I think was your intent. In any case, you want to update the existing car, not delete and re-add it (at least that's my assumption).

_ctx.Cars.Add(car);

This will always add a new car.

You want something more like:

var ctxCar = _ctx.Cars.SingleOrDefault(c => c.CarId = car.CarId);

if (ctxCar == null)
{
  return false;
}

//here you want map properties from your parameter to your context's car
ctxCar.Property1 = car.Property1;
//etc.

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

Comments

0

Is _ctx an EF context? If so, attaching should work:

// connect to context
_ctx.Cars.Attach(car);
// check for updated info
var entry = _ctx.Entry(car);
entry.Property(e => e.NumberOfDoors).IsModified = true;
// save changes
_ctx.SaveChanges();

Otherwise, Phil is correct:

_ctx.Cars.Add(car);

will always give you a new record

Comments

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.