update values in selected columns in using EF core - asp.net-core

I am new to ASP.NET core and EF Core. I need some help to get update values in selected colums in using EF core.
I need my view to provide List of students and give an option to updated FeePaid only with out giving an option to modify rest of the data.I have tried to modify "TryUpdateModelAsync" only include fee Paid as shown below but it updates rest of the fields with null value. I am working on SQL server LocalDb for now in visual studio 2019 and Code will be published in Azure.
Thanks for your help.
TryUpdateModelAsync<Student>(
studentToUpdate,
"student",
s=> s.FeePaid)
In SQL I can write a query to updated only selected colums with new values.
UPDATE table_name
SET column1 = value1, column2 = value2
WHERE condition;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
Student = await _context.Students.FindAsync(id);
if (Student == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int id)
{
var studentToUpdate = await _context.Students.FindAsync(id);
if (studentToUpdate == null)
{
return NotFound();
}
if (await TryUpdateModelAsync<Student>(
studentToUpdate,
"student",
s => s.FirstMidName, s => s.LastName, s => s.EnrollmentDate, s=> s.Confirmed, s=> s.FeePaid))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
return Page();
}

Related

Asp.net core api I can't enter more than one data on the same line

I have 3 tables, customer table has one to many relation with the other tables
a customer needs to add more than one address and phone number. With HTTPGET, I can pull data as follows, but I cannot perform crud operations.
enter image description here
GET:
[HttpGet("{id}")]
public async Task<ActionResult<Customer>> GetCustomer(int id)
{
var customers = _context.Customers
.Include(customer => customer.Adresses)
.Include(customer=> customer.Phones)
.Where(customer => customer.CId == id)
.FirstOrDefault();
if (customers == null)
{
return NotFound();
}
return customers;
}
POST:
[HttpPost]
public async Task<ActionResult<Customer>> PostCustomer(Customer customer)
{
_context.Customers.Add(customer);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException)
{
if (CustomerExists(customer.CId))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtAction("GetCustomer", new { id = customer.CId }, customer);
}
I can't enter more than one data on the same line
I want to receive customer information (how many addresses and phone numbers) at the same time as a record, I don't know how to do this.

Can't use select after include in repository pattern ASP.NET Core

I'm new to ASP.NET Core and I'm trying to get just the username from user by using select, but I can't.
Maybe this question is bad but I just started a few days ago. If you can help please go ahead and thanks in advance
the error is here:
public async Task<IActionResult> GetAllOrders()
{
var orders = await _unitOfWork.Orders.GetAll(o => o.IsReady == false,
orderBy: item => item.OrderBy(x => x.OrderDate),
include:i=>i.Include(x=>x.User).Select(x=>x.User.UserName));
var results = _mapper.Map<IList<OrderDTO>>(orders);
return Ok(results);
}
the function in the generic repository:
public async Task<IList<T>> GetAll(Expression<Func<T, bool>> expression = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
Func<IQueryable<T>, IIncludableQueryable<T, object>> include = null)
{
IQueryable<T> query = _db;
if (expression != null)
{
query = query.Where(expression);
}
if (include != null)
{
query = include(query);
}
if (orderBy != null)
{
query = orderBy(query);
}
return await query.AsNoTracking().ToListAsync();
}
the error is here
the function in the generic repository
I think you should not have that Select statement because it makes the Include syntax invalid. You should be able to access the UserName like this:
foreach(var order in orders)
{
var userName = order.User.UserName;
}

PUT request to API is setting values to NULL

I have this .Net Core API controller below that does a PUT request.
The table affected in Sql Server, looks like this:
carID (varchar(15), NULL)
optionID (varchar(15), NOT NULL)
optionDescription (varchar(255), NULL)
optionType (varchar(50), NULL)
factoryID (varchar(15), NULL)
In testing, I am sending along the properties I want changed like this in my PUT API call:
{
" optionID": "633fr",
"optionDescription": "Full Tech Package A"
}
It does update the entry in the database, but it's also setting all the values not sent in the PUT call to NULL. So while it does update optionDescription, it is setting all the other values to NULL except optionID.
How do I stop it from setting the other values?
thanks!
Here is the controller:
// PUT: api/CarOptions/5
[HttpPut("{id}")]
public async Task<IActionResult> PutCarOptions(Guid id, CarOptions carOptions)
{
if (id != carOptions.OptionId)
{
return BadRequest();
}
_context.Entry(carOptions).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CarOptionsExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
According to your description, I suggest you could try to attach the model firstly and then set the specific property IsModified to true.
This will only update specific fields instead of updating whole model.
More details, you could refer to below example:
// PUT: api/CarOptions/5
[HttpPut("{id}")]
public async Task<IActionResult> PutCarOptions(Guid id, CarOptions carOptions)
{
_context.Documents.Attach(carOptions);
_context.Entry(carOptions).Property(x => x.optionDescription).IsModified = true;
_context.SaveChanges();
return NoContent();
}

How to update a many to many relationship that has fields extra to its foreign keys

I’m implementing a project using asp.net core. Employing DB first approach and creating models in Visual studio, in SQl server I have two tables called API and Applicant that have many to many relationship and there is also their junction table called ApiApplicant.
Suppose these 3 tables has the following fields each:
Api: ID, name,date
Applicant:Id,name,type
ApiAppliant:Id,ApiID,ApplicantId,reqDate,gateId
My ApiApplicant table also has many to one relationship with another table called Gate.Gate table has the following fields:Id, name,
Now I want to know how can I update ApiApplicant table in my code.
I appreciate if anyone solve the above problem by showing me a sample relevant linq code.
It is not clear how you would like to update the junction table.You does not show any code.
Anyany, you could firstly remove all original records which you want to update and then add new records.
Below is a demo which updates an existing Api's related Applicants.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(long id, Api api)
{
if (id != api.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
//your new ApplicantIds
var newSelectedApplicantIds = new int[] { 3,4 };
var apiApplicants = new List<ApiApplicant>();
var apiAppList = await _context.ApiApplicant.Where(a => a.ApiID == api.Id).ToListAsync() ;
_context.RemoveRange(apiAppList);
foreach (var newid in newSelectedApplicantIds)
{
var item = new ApiApplicant()
{
ApiID = api.Id,
ApplicantId = newid,
};
apiApplicants.Add(item);
}
_context.AddRange(apiApplicants);
_context.Update(api);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
}
return RedirectToAction(nameof(Index));
}
return View(api);
}

send parameter to windows azure mobile server script in c# for Windows 8 Store app

I modified the "Read" operation on my Windows Azure Mobile Services Preview table (named "Item") as follows:
Javascript:
function read(query, user, request)
{
var howRead;
if(howRead == "unique")
{
var sqlUnique = "SELECT DISTINCT ? FROM Item WHERE qProjectCode = ?";
mssql.query(sqlUnique)
request.execute();
}
else if (howRead == "column")
{
var sqlColumn = "SELECT ? FROM Item WHERE qProjectCode = ?";
mssql.query(sqlColumn)
request.execute();
}
else if (howRead == "all")
{
var sqlAll = "SELECT * FROM Item WHERE qProjectCode = ?";
mssql.query(sqlAll)
request.execute();
}
}
This simply species when I want a unique list of a single column's values returned, all items in a single column, or all columns, respectively, all while limiting the read to those records with a given project code.
Right now, this works in C#, but scans the entire table (with other project codes) and always returns all columns. This is inherently inefficient.
c#
var client = new MobileServiceClient("[https path", "[key]");
var table = client.GetTable<Item>();
var query1 = table.Where(w => w.QProjectCode == qgv.projCode && w.QRecord == (int)lbRecord.Items[uStartRecordIndex]);
var query1Enum = await query1.ToEnumerableAsync();
foreach (var i in query1Enum)
{
// process data
}
How do I alter the c# code to deal with the Javascript code? Feel free to critique the overall approach, since I am not a great programmer and can always use advice!
Thanks
A few things:
In your server code, the mssql calls are not doing anything (useful). If you want to get their results, you need to pass a callback (the call is asynchronous) to it.
Most of your scenarios can be accomplished at the client side. The only for which you'll need server code is the one with the DISTINCT modifier.
For that scenario, you'll need to pass a custom parameter to the server script. You can use the WithParameters method in the MobileServiceTableQuery<T> object to define parameters to pass to the service.
Assuming this data class:
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Other { get; set; }
public string ProjectCode { get; set; }
}
The code below can be used to accomplish the scenarios 2 and 3 at the client side only (no script needed at the server side). The other one will need some script, which I'll cover later.
Task<IEnumerable<string>> ReadingByColumn(IMobileServiceTable<Item> table, string projectCode)
{
return table
.Where(i => i.ProjectCode == projectCode)
.Select(i => i.Name)
.ToEnumerableAsync();
}
Task<IEnumerable<Item>> ReadingAll(IMobileServiceTable<Item> table, string projectCode)
{
return table.Where(i => i.ProjectCode == projectCode).ToEnumerableAsync();
}
Task<IEnumerable<string>> ReadingByColumnUnique(IMobileServiceTable<Item> table, string projectCode)
{
var dict = new Dictionary<string, string>
{
{ "howRead", "unique" },
{ "projectCode", projectCode },
{ "column", "Name" },
};
return table
.Select(i => i.Name)
.WithParameters(dict)
.ToEnumerableAsync();
}
Now, to support the last method (which takes the parameters, we'll need to do this on the server script:
function read(query, user, request)
{
var howRead = request.parameters.howRead;
if (howRead) {
if (howRead === 'unique') {
var column = request.parameters.column; // WARNING: CHECK FOR SQL INJECTION HERE!!! DO NOT USE THIS IN PRODUCTION!!!
var sqlUnique = 'SELECT DISTINCT ' + column + ' FROM Item WHERE ProjectCode = ?';
mssql.query(sqlUnique, [request.parameters.projectCode], {
success: function(distinctColumns) {
var results = distinctColumns.map(function(item) {
var result = [];
result[column] = item; // mapping to the object shape
return result;
});
request.respond(statusCodes.OK, results);
}
});
} else {
request.respond(statusCodes.BAD_REQUEST, {error: 'Script does not support option ' + howRead});
}
} else {
// no server-side action needed
request.execute();
}
}