I'm having a problem with Web API where I want to create a new object in SQL Server. The PUT method is used to update an expensenote. An expensenote contains dailyexpensenotes. A dailyexpensenote contains individualexpenses.
In the GUI, a user that edits his expensenote can:
- Fill in an empty individualexpense with value > 0 (Creates a new individualexpense)
- Change an existing individualexpense (Updates the existing individualexpense)
- Clear an individualexpense/change value to 0 (Deletes the existing individualexpense)
After this the user clicks save and the entire expensenote is sent by ajax call to the web service. Nr 2 and Nr 3 are working as desired but the Nr 1 doesn't work and gives no error.
PUT method
// PUT api/expenses/5
public void Put(int id, [FromBody]Expensenote exUpdate)
{
expensenote ex = (from e in db.expensenotes
where e.ID == id
select e).FirstOrDefault();
if (ex == null)
{
//return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Request was not found.");
}
else
{
foreach (Expensenotedaily d in exUpdate.dailyExpenses)
{
var daily = ex.expensenotedailies.SingleOrDefault(da => da.ID == d.ID);
daily.city = d.city;
daily.dailyallowance = d.dailyallowance;
foreach (Expenseindividual i in d.individualExpenses)
{
expenseindividual individual = daily.expenseindividuals.SingleOrDefault(ind => ind.ID == i.ID);
if (i.value == 0)
{
if (!(individual == null))
{
db.expenseindividuals.Remove(individual);
}
}
else
{
if (!(individual == null))
{
individual.value = i.value;
}
else
{
expenseindividual newInd = db.expenseindividuals.Create();
newInd.typecode_ID = i.expensetypeID;
newInd.daily_ID = daily.ID;
newInd.typecode = db.typecodes.SingleOrDefault(t => t.ID == i.expensetypeID);
newInd.expensenotedaily = daily;
newInd.value = i.value;
newInd.creditcard = false;
db.expenseindividuals.Add(newInd);
//SOLUTION: db.SaveChanges();
}
}
}
}
db.SaveChanges();
}
}
expenseindividual datamodel class
public partial class expenseindividual
{
public expenseindividual()
{
this.supplementalinfoes = new HashSet<supplementalinfo>();
}
public int ID { get; set; }
public double value { get; set; }
public bool creditcard { get; set; }
public int daily_ID { get; set; }
public int typecode_ID { get; set; }
public virtual expensenotedaily expensenotedaily { get; set; }
public virtual typecode typecode { get; set; }
public virtual ICollection<supplementalinfo> supplementalinfoes { get; set; }
}
When I debug I see that all attributes are passed correctly. Using newInd = new expenseindividual() instead of Create() doesn't fix the problem. I tried setting the expenseindividual.ID manually and this makes the insert work but it must auto increment and auto increment is enabled. So I'm really wondering what causes the problem here and how I can fix it?
If I understand you correctly, you are trying to insert a new expense note into the database when one does not already exist?
Firstly... this code currently ignores expense notes that do not already exist in the database...
ex
will always be null when you pass an id of an expense note that does not already exist inside of the database, therefore no code will be run.The convention is that typically PUT is always used to update a record, POST is used instead when trying to create one but thats up to you.
You need to implement your logic to create a new record within the if statement, replacing the commented out return statement.