issue updating an Api value in c# asp.net [duplicate] - c#

This question already has answers here:
How to update only one field using Entity Framework?
(17 answers)
Closed 8 years ago.
Hey guys I am curious in how I can update just one column at a time in a database. When I run something such as postman or fiddle to query a Put to my database. If I only include one field, it sets all of the other fields = to null. Is there anyway I would be able to leave the other fields blank when I query the PUT and it will only change the one field I am asking the PUT to update? Sorry if my explanation is not good I am new to using API's.
Here is my PUT method (basic scaffold):
public IHttpActionResult PutUser(int id, User user)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != user.Id)
{
return BadRequest();
}
db.Entry(user).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!UserExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
When I want to update, say just the first name, and there is already a first and last name in the database. After the PUT method the last name would be set to null. So I debugged and noticed that the user it is taking in in the parameter already has last name set to null. Any advice would be greatly appreciated!

I'm guessing that you are sending a blank user with just information in the column that you want to update. Well what you should do is read the user details first, then change the column/field as required, then send this new user object back to the API Put method
Edit
Basically you can't really specify a single column/field to update using this API pattern. Look at your constructor, there's no parameter to tell the code which column you want to update. (You could test for nulls, but I would strongly advise against it). Your code is telling EntityFramework to update the database with the User object that you provide.
Therefore you need to first retrieve the user that you want to update (using a GET), and only change the field that you want to change, then send the updated User object back to the API Put method. If you send a User object with NULL values, then these NULL values will be saved to the database.
If you really want to be able to specify columns, you can write separate PUT method overloads that will only update the column you want. However programming this way requires more effort and more maintenance, and I would advise against it.

Related

How do I update a MongoDB document but exclude a specific field?

I am creating a web API. I need something like this:
When I updating a document at mongodb, I do not want to update a field (createdAt). I know that I can get a old value of that field and manuelly and then put it updated object but it requires one more unnecessarry request to db. I do not want this. My method is here:
public async Task<bool> UpdateAsync(Customer updatedCustomer)
{
var result = await _mongoService.Customers.ReplaceOneAsync(c => c.Id == updatedCustomer.Id, updatedCustomer);
return result.IsModifiedCountAvailable && result.ModifiedCount>0;
}
Is there any way to exclude one property of my Customer class (createdAt) and left it same everytime. BTW please do not recomend that set all properties update one by one by using "Set" method. Thank you.
I'm not sure if there is a way other than to set the properties one by one, but researching the following may be helpful or suggestive of something new.
In Mongodb you can use some decoration to do like [BsonIgnore] but it will ignore it every time
One alternative would be to load the document you wish to modify, followed by calling BsonDocument.Merge with overwriteExistingElements set to true in order to merge your changes.

how to search other field than id

I'm following and implementing a side project from:
https://learn.microsoft.com/es-mx/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.0&tabs=visual-studio
But in the part where [HttpGet("{id}")] is invoked, it works only with the id field, but I want to retrieve a JSON stored in the DBmemory, with other field instead of id; in this case I want to manage data by field TAG.
How can I accomplish this?
I've try to change all the id parts to TAG, which is the field I'm looking for, but when I do this, the post method breaks up.
// GET: api/Maquinas/5
[HttpGet("{id}")]
public async Task<ActionResult<Maquina>> GetMaquina(string id)
{
// HERE. i need to find data with the field of "TAG" not "id"
var maquina = await _context.Maquinas.FindAsync(id);
if (maquina == null)
{
return NotFound();
}
return maquina;
}
Don't get stuck on the fact that is called id. You could make use of this endpoint and instead of passing the value of id to pass the value of tag, api/Maquinas/tagvalue.
Later on you should use this value in the call you make to retrieve the entity you are looking for.
_context.Maquinas.FirstOrDefaultAsync(maquina => maquina.Tag == id);
I have assumed here that the property on which you want to filter is called Tag and it's type is string. It is quite probable, at least the name of the property to not be this one. So you have to change the above code correspondingly.
This will fix your problem, but you should not consider this a best practice. The semantics of your API would be broken. The very reason, I shared the above, is to show you that the name of the parameter id is irrelevant with that you pass. There isn't any check that would halt you for passing there "anything". The reason I wrote that the semantics of your API would be broken is that since this is going to be a REST api, someone would expect an endpoint like the following one:
api/Maquinas/1
for getting the entity with id 1.

twilio twimlresult post to sql server

So, adapting some of the code from the tutorial here:
I have got a twilio app up and running and it correctly posts and inserts calls into my sql server, although I am trying to add additional fields to be inserted and I ran into some issues. In my controller, this is the method i am using:
[HttpPost]
public TwiMLResult Create(
[Bind(Include = "QuestionId,RecordingUrl,Digits,CallSid,From")]
Answer answer)
{
_answersRepository.Create(answer);
var nextQuestion = new
QuestionFinder(_questionsRepository).FindNext(answer.QuestionId);
return TwiML(nextQuestion != null ? new Response(nextQuestion).Build() :
ExitResponse);
}
My question is two parts. First, how can I add more fields to be added to my sql table? I tried adding StartTime, EndTime, Duration after ,From and adding it to the Model, synced my database so I can see the columns on the table but nothing actually get's inserted. I put the data types as string so maybe that was the issue? I could not tell from the twilio documentation what datatype those fields wer.
The second part of the question is can I put custom fields into that Bind(Include) statement? For instance, can I create a variable called Name and then have the TwiMLResult Create send a string Name along with the twilio data with it as well? Of course, I would add it to the model class and thus to the table.
I guess my problem is is that I don't understand what is happening with the TwiMLResult Create method very well. What is happening exactly? This method here is what is actually RECEIVING the data coming from twilio, correct? and the _answersRepository.Create is what writes it to the database? So I should be able to add more fields and have them written to the db just fine I would think. I just am not sure why the StartTime, EndTime, Duration information isn't coming through to this point. Similarly, I am not sure how to add a custom variable, for instance, to pass the person's name to this point and have it written to the db.
I hope this all makes sense and isn't too convoluted to understand. Thank you in advance everyone! I really appreciate the help!
Syd
EDIT: Basically, I determined that those fields do not come through and thus were passing null values. To answer the second part of my question, you can definitely pass any query values and record them (which is what I ended up doing).

If I have default value set as NULL at database, can I ignore while I adding it in c#? via using MVC4

This is the example what I had done on my program.
Currently I had set my database for accepting the datetime Allow NULL and also default value as NULL.
The datetime i set it to nullable like this:
System.DateTime? EntryTime
Then here is my code in MODEL, I do it in the model so that every function who need it can use it.
UserLogin newItems = db.MyItems.Create();
newItems.Id = id;
//newItems.EntryTime = null;
db.UserLogins.Add(newItems);
db.SaveChanges();
Even I didnt commented it, it still goes into the same error result.
when I come to update the data into database it give me "System.Data.Entity.Validation.DbEntityValidationResult" error.
I totally out of idea. Can someone help me?
EDIT 1 I made a mistake on variable.
The only given error is System.Data.Entity.Validation.DbEntityValidationResult and no detailed information given, that's why I am totally out of idea.
Most ORMs won't care about the default value on the table; they care about the object - and the object has a value (a null in this case), whether or not you specify it explicitly. So typically, it will dutifully pass down the null as part of the insert, and the default value will not be used. There may be ways of overriding this in some ORMs, but personally I wouldn't count on it.
Have you tried inserting the data with insert statement?
INSERT INTO `table` (id) VALUES ('id_values');
But I guess you'll have to create a custom module for this. With my MVC application, I use the service-repository approach. Entity Framework is so frustrating.

Trying to separate logic from controller in an MVC Entity Framework app - What is happening here?

Based on my last question, I have tried to separate the business logic from my controller completely.
This however has left a problem which I understand why, but not how to fix.... And, I do not understand why it is doing what is doing.
In my controller, I had the following:
public User GetCurrentUser()
{
User user = db.Users.SingleOrDefault(x => x.UserName == User.Identity.Name);
return user;
}
I now know about [NonAction] which fixes the security concern - however, I know this doesn't follow best practices of not having any non controller stuff in a controller. For this reason, I moved to a new class and modified it to the following:
public User GetCurrentUser(string name)
{
User user = db.Users.SingleOrDefault(x => x.UserName == name);
return user;
}
I have an edit method which before simply set various fields in the user object, then called db.SaveChanges(). This however is now causing issues - I believe it is due to calling the command on a db object that doesn't actually have the object loaded.
But, the part that I really do not understand is when I am redirected back to the home page and perform GetCurrentUser() again, I am presented with the edited details I changed... These are not stored in the database and it is only when I restart the application it goes back to the database results.
I am finding this very confusing! What is happening here and where are the object being stored?
And, how do I fix it? I have tried making the new Class's db function public and calling it's SaveChanges() method, but, this is resulting in the same problem - data that is not being saved to the database.
Anyway, quite frankly, I really liked calling it via just GetCurrentUser(), I wanted this due to the fact I wanted to change the way the user was loaded in the future - but, now that I have to call it via GetCurrentUser(User.Identity.Name), and make other modifications, I think it wouldn't be that much harder to just skip on the method and call the Lambda query directly instead... It just seems it will save a lot of trouble.
Based on the detail in your question, you need to make sure you attaching your Entity object e.g db.Users.Attach(updatedUser)
And then change its state
e.g db.ObjectStateManager.ChangeObjectState(updatedUser, EntityState.Modified)
Before you call db.SaveChanges()
The edit functions I've written for my MVC app usually have one more line of code before I call SaveChanges:
_db.ApplyCurrentValues(OriginalEntity.EntityKey.EntitySetName, NewEntity);
_db.SaveChanges();
Also, maybe I'm missing something but wouldn't this (below) be a simpler way to update the user information in the database?
Membership.UpdateUser();
As for the reason why the non-database data is still showing up for you, I think that is because when you call GetCurrentUser it caches information on the client side. I'm sure someone with more experience here can give a more detailed (or more correct answer) on that part.

Categories