Scott
Scott

Reputation: 467

Using AngularJS's $http.put method

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;
};

Upvotes: 0

Views: 523

Answers (2)

user270576
user270576

Reputation: 997

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

Upvotes: 0

Phil Sandler
Phil Sandler

Reputation: 28026

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;

Upvotes: 2

Related Questions