I am trying to delete a row from my database based on a Primary Key ID field. When I try to do it, all of the code executes without any errors, but the item doesn't get deleted from the database.
I'm passing the item to my C# backend from an angular frontend call like this:
delete(customerId: number, materialCustomerId: number): Observable<Response> {
return this.http.delete(`${this.getBaseUrl()}/${customerId}/materialcustomer/${materialCustomerId}`).catch(error => this.handleError(error));
}
It then hits my controller method:
[HttpDelete]
[Route("{customerId}/materialcustomer/{materialCustomerId}")]
[AccessControl(Securable.Customer, Permissions.Delete, Permissions.Execute)]
public async Task Delete(int customerId, int materialCustomerId)
{
await _materialCustomerDeleter.DeleteAsync(MaterialCustomer.CreateWithOnlyId(materialCustomerId), HttpContext.RequestAborted);
}
Manipulator method:
public async Task DeleteAsync(MaterialCustomer model, CancellationToken cancellationToken = default(CancellationToken))
{
if (model == null)
throw new ArgumentNullException(nameof(model));
await _materialCustomerDeleter.DeleteAsync(new TblMaterialCustomer { MaterialCustomerId = model.MaterialCustomerId }, cancellationToken);
if (cancellationToken.IsCancellationRequested)
return;
await _customerWriter.CommitAsync(cancellationToken);
}
and finally, my repository method:
public async Task DeleteAsync(TblMaterialCustomer entity, CancellationToken cancellationToken = new CancellationToken())
{
var item =
await _context.TblMaterialCustomer.FirstOrDefaultAsync(i => i.MaterialCustomerId == entity.MaterialCustomerId, cancellationToken);
if (item == null || cancellationToken.IsCancellationRequested)
return;
_context.SetModified(item);
}
What am I missing?
Assuming that await _customerWriter.CommitAsync(cancellationToken); calls through to the same DbContext instance and calls method SaveAsync you should re-write the delete method like this:
public void Delete(TblMaterialCustomer entity)
{
_context.TblMaterialCustomer.Remove(entity);
}
Also it would probably be a good idea to return a result from the WebAPI call, although it is not required, like OK/200.
public async Task<IHttpActionResult> Delete(int customerId, int materialCustomerId)
{
await _materialCustomerDeleter.DeleteAsync(MaterialCustomer.CreateWithOnlyId(materialCustomerId), HttpContext.RequestAborted);
return Ok();
}
Related
I am trying to access a property on the user within UpdateUser(userModelFromRepo), when I change the parameters to accept Task I cannot access the User.modifiedAt property. Is there a way to do so? Alternatively, is there a way to just return the user object back and remain async from GetUserById()? await _repository.UpdateUser(userModelFromRepo) says that it cannot convert from Task User to User.
[HttpPut("{id}")]
public async Task<ActionResult> UpdateUser(int id, UserUpdateDto userUpdateDto)
{
var userModelFromRepo = _repository.GetUserById(id);
if (userModelFromRepo == null)
{
return NotFound();
}
await _mapper.Map(userUpdateDto, userModelFromRepo);
await _repository.UpdateUser(userModelFromRepo);
await _repository.SaveChanges();
return NoContent();
}
public async Task<User> GetUserById(int id)
{
return await _context.User.FirstOrDefaultAsync(u => u.Id == id);
}
public async Task UpdateUser(User userModelFromRepo)
{
await Task.Run(() =>
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
user.ModifiedAt = DateTime.UtcNow;
});
}
You need to await the call like this
var userModelFromRepo = await _repository.GetUserById(id);
Full code:
[HttpPut("{id}")]
public async Task<ActionResult> UpdateUser(int id, UserUpdateDto userUpdateDto)
{
var userModelFromRepo = await _repository.GetUserById(id);
if (userModelFromRepo == null)
{
return NotFound();
}
await _mapper.Map(userUpdateDto, userModelFromRepo);
await _repository.UpdateUser(userModelFromRepo);
await _repository.SaveChanges();
return NoContent();
}
Also, if you don't do anything else in your UpdateUser method you can remove the Task.Run stuff, it doesn't add any value.
public Task UpdateUser(User userModelFromRepo)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
user.ModifiedAt = DateTime.UtcNow;
return Task.CompletedTask;
}
I am using asp.net core web api and I need to execute one task OneTask and on successful execution of OneTask it should return OK staus otherwise error response. I want HttpResponseMessage and can something return return Ok(awit OneTask());
[HttpPost]
public async Task<OkObjectResult> Post()
{
await OneTask;
return Ok(new HttpResponseMessage(HttpStatusCode.OK));
}
public async Task OneTask()
{
await //some task
}
The IActionResult<T> interface is the best practice to respond to the client.
So change the code like this :
[HttpPost]
[Route("PostWithValue")]
public async Task<IActionResult> PostWithValue()
{
var result = await OneTaskWithReturnValue();
return Ok(result);
}
public async Task<bool> OneTaskWithReturnValue()
{
await Task.Delay(100);
return true;
}
Also, beware of async void (Task without <T>) that is a bad idea because you have problem with handling exceptions :
In a nutshell:
[HttpPost]
[Route("PostWithValue")]
public async Task<IActionResult> PostWithValue()
{
var result = await OneTaskWithReturnValue();
if (!result)
{
return BadRequest("Message for Error");
}
return Ok("Message for OK Status");
}
public async Task<bool> OneTaskWithReturnValue()
{
await Task.Delay(100);
// Do you task
return true;
}
Requirement
FormStateModel already contains FIRST input that users types.
Code
Simply I want to put the string that is in activity.Text inside FormStateModel:
private IDialog<FormStateModel> MakeRootDialog(string input)
{
return Chain.From(() => new FormDialog<FormStateModel>(
new FormStateModel() { Question = input },
ContactDetailsForm.BuildForm,
FormOptions.None));
}
=
public async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
await Conversation.SendAsync(
toBot: activity,
MakeRoot: () => this.MakeRootDialog(activity.Text));
}
else
{
await HandleSystemMessageAsync(activity);
}
var response = this.Request.CreateResponse(HttpStatusCode.OK);
return response;
}
On ConversationUpdate I start conversation simply by asking "Please type your Question:"
private static async Task<Activity> HandleSystemMessageAsync(Activity message)
{
switch (message.Type)
{
case ActivityTypes.DeleteUserData:
break;
case ActivityTypes.ConversationUpdate:
await Welcome(message);
break;
(...)
In that way:
private static async Task Welcome(Activity activity)
{
(...)
reply.Text = string.Format("Hello, how can we help you today? Please type your Question:");
await client.Conversations.ReplyToActivityAsync(reply);
(...)
}
But I can not find a way how to pass it. In this case this exception occurs:
anonymous method closures that capture the environment are not serializable, consider removing environment capture or using a reflection serialization surrogate:
Is there any way around that to populate state model at this step?
Solved by calling RootDialog inside MessagesController, then Calling new FormDialog by context.Call(form, (...));
public async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{
await Conversation.SendAsync(activity, () => new LayerDialog());
}
LayerDialog:
[Serializable]
public class LayerDialog: IDialog<IMessageActivity>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(this.OnMessageReceivedAsync);
}
private async Task OnMessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var awaited = await result;
FormStateModel model = new FormStateModel();
model.Value = awaited.Text;
var form = new FormDialog<FormStateModel >(model ,
BuildForm , FormOptions.PromptInStart);
context.Call(form , this.AfterResume);
}
I'm trying to implement a way to lock a user out but keep all their data in the system. I have been reading the documentation for SetLockoutEnabledAsync and it seems to be the thing I'm looking for.
I implemented the below code in my Controller, but I'm not sure if it's correct or if I'm having a problem with the view. So my question is in two parts: Is this code correct, and if so, what should the View look like?
public async Task <IActionResult> Disable (ApplicationUser Id)
{
if(Id == null)
{
return NotFound();
}
var en = await _usermanager.SetLockoutEnabledAsync(Id, true);
if( en == null)
{
return NotFound();
}
return View(en);
}
[HttpPost, ActionName("Disable")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DisableConfirmed(ApplicationUser Id)
{
var en = await _usermanager.SetLockoutEnabledAsync(Id, true);
await _usermanager.SetLockoutEnabledAsync(Id, true);
await _application.SaveChangesAsync();
return RedirectToAction("ListUsers", "Admin");
}
Can somebody tell if there is a way to get all users async in ASP.NET Identity 2?
In the UserManager.Users there is nothing async or find all async or somwething like that
There is no way to do this asynchronously with the UserManager class directly. You can either wrap it in your own asynchronous method: (this might be a bit evil)
public async Task<IQueryable<User>> GetUsersAsync
{
return await Task.Run(() =>
{
return userManager.Users();
}
}
Or use the ToListAsync extension method:
public async Task<List<User>> GetUsersAsync()
{
using (var context = new YourContext())
{
return await UserManager.Users.ToListAsync();
}
}
Or use your context directly:
public async Task<List<User>> GetUsersAsync()
{
using (var context = new YourContext())
{
return await context.Users.ToListAsync();
}
}