I am connecting to the Quickbooks api, download the employees inforamtion and saving it to my local database. I am using angularjs, webapi to accomplish this. I am getting the following error when I am saving the info to database. I do see all the functions have async and await. Can some body please help me why I am getting this error.
Error :
Server Error in '/' Application.An asynchronous module or handler completed while an asynchronous operation was still pending.
Problem is happening in the below pasted piece of code:
var candidate = await CandidateLoginBL.AddCandidateByEmployeeAsync(new CandidateLoginBO()
{
FirstName = e.GivenName,
MiddleName = e.MiddleName,
LastName = e.FamilyName
});
}
});
The full flow is as follows :
js :
QuickbookModule.factory('QuickbookService', ['$http', function ($http) {
return {
getQuickbooksSync: function () {
return $http({
url: '/api/QuickbookService/syncQuickbooks',
method: 'GET',
params: { IdCompany: sessionStorage.CID }
});
}
API Controller :
[HttpGet]
[Route("syncQuickbooks")]
public async Task<IHttpActionResult> syncQuickbooks(int IdCompany)
{
var result = await QuickbooksBL.FullQuickbooksSync(IdCompany);
return Ok(result);
}
QuickbooksBL :
public static async Task<List<IncompleteEmp>> FullQuickbooksSync(int IdCompany)
{return await SyncronizeEmps(IdCompany); }
public static async Task<List<IncompleteEmp>> SyncronizeEmps(int companyId)
{
......
List<EmployeeBO> empList = new List<EmployeeBO>();
await AddToHumanEfits(companyId, inQBEmpsInfo); ....
}
return IncompleteEmps;
}
public static async Task AddToHumanEfits(int companyId, List<EmployeeQbOnlineBO> qbEmpsList)
{
....
qbEmpsList.ForEach(async e =>
{
// Add a record into Candidate Login.
var candidate = await CandidateLoginBL.AddCandidateByEmployeeAsync(new CandidateLoginBO()
{
FirstName = e.GivenName,
MiddleName = e.MiddleName,
LastName = e.FamilyName });
}
});
}
CandidateContactBL :
public static async Task<CandidateLoginBO> AddCandidateByEmployeeAsync(CandidateLoginBO model)
{
return await CandidateLoginDAL.AddCandidateByEmployeeAsync(model);
}
CandidateContactDAL :
public static async Task<CandidateLoginBO> AddCandidateByEmployeeAsync(CandidateLoginBO model)
{
CandidateLoginBO candidate = new CandidateLoginBO();
candidate = await GetByUserNameAsync(new CandidateLoginBO() { Email = model.Email }); candidate = await AddEmployeeAsync(model);
return candidate;
}
This kind of error is commonly caused by async void. And I see one right here:
qbEmpsList.ForEach(async e =>
{
...
});
You'd probably want to make this into a regular foreach:
foreach (var e in qbEmpsList)
{
...
}
Related
I'm working on an ASP.NET Core MVC application and I have a view who do a post request as:
$.ajax({
url:'/Advertisers/ActiveAdvertiser?id='+id+'&isActive='+!isActive,
method: 'POST',
success: function(r){
Swal.fire("Inactivated!", "Advertiser inactivated successfully", "success");
},
error: function (request) {
console.log(request.responseText)
Swal.fire("Error!", "Something went wrong, please try again`", "warning");
}
});
Controller:
[HttpPost]
public async Task<JsonResult> ActiveAdvertiser(int id, bool isActive)
{
var advertiser = await _advertisersService.GetAdvertiserByAdvertiserIdAsync(id);
if (advertiser != null)
{
var model = AssingAdvertiserViewModel(advertiser, id);
model.IsActive = isActive;
var result = await _advertisersService.UpdateAdvertiserAsync(model, GetCurrentUserAsync().Id);
if (result != null)
{
return Json(new { result = "OK" });
}
}
return Json(new { result = "BadRequest" });
}
Post method services:
public Task<Advertiser?> GetAdvertiserByAdvertiserIdAsync(int advertiserId)
{
return _db.Advertisers
.Include(a => a.Address)
.Include(pc => pc.PrimaryContact)
.Include(ac => ac.AlternateContact)
.FirstOrDefaultAsync(x => x.AdvertiserId == advertiserId);
}
private AdvertiserViewModel AssingAdvertiserViewModel(Advertiser advertiser, int id)
{
var model = new AdvertiserViewModel()
{
//Fill model here
};
return model;
}
public async Task<Advertiser?> UpdateAdvertiserAsync(AdvertiserViewModel model, int updatedById)
{
var advertiser = await GetAdvertiserByAdvertiserIdAsync(model.AdvertiserId);
if (advertiser is null)
return null;
advertiser.Name = model.Name;
// fill model here
await _db.SaveChangesAsync();
return advertiser;
}
The problem is I do the first request, and it returns Success with any issues, but if I try to do a second one, it throws an exception:
System.InvalidOperationException: A second operation was started on
this context instance before a previous operation completed. This is
usually caused by different threads concurrently using the same
instance of DbContext.
If I stop the project and run it again it works one time again and in the second time get the error again
I read about this issue in other questions, and apparently is because you don't use the await services, I check my code and almost everything uses await. Can someone see something that I don't see? Regards
You could check this document for how to handle this error:
Therefore, always await async calls immediately, or use separate DbContext instances for operations that execute in parallel.
So you could check if misssing the await keyword on async operation
and use separate Dbcontext instances with DbcontextFactory as below:
regist the factory in service collection:
builder.Services.AddDbContextFactory<SomeContext>();
inject it into controller/Service/Somewhereelse:
public class SomeEntitiesController : Controller
{
private readonly IDbContextFactory<SomeContext> _factory;
public SomeEntitiesController(IDbContextFactory<SomeContext> factory)
{
_factory = factory;
}
}
create a new dbcontext:
_factory.CreateDbContext()
I solve this by adding ServiceLifetime.Transient into my services as:
services.AddDbContext<ApplicationDbContext>(
options =>
options.UseSqlServer(Configuration.GetConnectionString("ApplicationDbConnection")),
ServiceLifetime.Transient
);
I have this Error
The Json value could not be converted to
System.Collections.Genereic.List
1[Blazor_fresh_project.Shared.Feedback]. Path: $ | LineNumber: 0 |
BytePositionInLine: 1.
when I'm trying to CreateObj in this method :
public async Task<List<Feedback>> CreateFeedback(Feedback feedback)
{
var resulte = await _httpClient.PostAsJsonAsync($"api/feedback",feedback);
string content = Newtonsoft.Json.JsonConvert.SerializeObject(resulte);
Console.WriteLine("Here is THE CONTENT " +content);
var feedbacks = await resulte.Content.ReadFromJsonAsync<List<Feedback>>();
return feedbacks;
}
This error happen at line :
var feedbacks = await resulte.Content.ReadFromJsonAsync<List<Feedback>>();
The console write :
Console debug
Do you have any suggestions or tips for debugging this kind of error?
Edit : api/feedback request
namespace Blazor_fresh_project.Server.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class FeedbackController : ControllerBase
{
List<Feedback> Feedbacks = new List<Feedback> {
new Feedback{Id=1,Name="arthur",Description="I think this is great",DateOfPost=DateTime.Now,Power=10},
new Feedback{Id=2,Name="Mario",Description=" coming soon",DateOfPost=DateTime.Now,Power=8},
new Feedback{Id=3,Name="Chipolo",Description="I think this is great",DateOfPost=DateTime.Now,Power=17},
new Feedback{Id=4,Name="Coco",Description=" coming soon",DateOfPost=DateTime.Now,Power=12},
new Feedback{Id=5,Name="Marguerite",Description="I think this is great",DateOfPost=DateTime.Now,Power=6},
new Feedback{Id=6,Name="Carine",Description=" coming soon",DateOfPost=DateTime.Now,Power=4}
};
[HttpGet]
public async Task<IActionResult> GetFeedbacks()
{
return Ok(Feedbacks);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetSingleFeedback(int id)
{
var feedback = Feedbacks.FirstOrDefault(f => f.Id == id);
if (feedback == null)
return NotFound("this feedback wasn't found");
return Ok(feedback);
}
[HttpPost]
public async Task<IActionResult> CreateFeedback(Feedback feedback)
{
feedback.Id = Feedbacks.Max(h => h.Id + 1);
Feedbacks.Add(feedback);
return Ok(feedback);
}
}
}
namespace Blazor_fresh_project.Client.Services
{
public class FeedbackService : IFeedbackService
{
private HttpClient _httpClient;
public FeedbackService(HttpClient httpClient)
{
_httpClient = httpClient;
}
[Authorize]
public async Task<List<Feedback>> GetFeedbacks()
{
return await _httpClient.GetFromJsonAsync<List<Feedback>>("api/feedback");
}
public async Task<Feedback> GetFeedback(int id)
{
return await _httpClient.GetFromJsonAsync<Feedback>($"api/feedback/{id}");
}
[Authorize]
public async Task<List<Feedback>> CreateFeedback(Feedback feedback)
{
var resulte = await _httpClient.PostAsJsonAsync($"api/feedback",feedback);
string content = Newtonsoft.Json.JsonConvert.SerializeObject(resulte);
Console.WriteLine("Here is THE CONTENT " +content);
var feedbacks = await resulte.Content.ReadFromJsonAsync<List<Feedback>>();
return feedbacks;
}
}
}
The 'Console' screenshot shows us a payload of a single Feedback item, the request-in-a-browser shows a list of Feedbacks.
Your code is doing a POST, the browser does a GET. Apparently you have an endpoint with different return types for GET and POST.
Post the (relevant) code of your controller if you need more help.
OK, so indeed you have. You can change your controller or what looks more logical, your client:
public async Task<Feedback> CreateFeedback(Feedback feedback)
{
var resulte = await _httpClient.PostAsJsonAsync($"api/feedback",feedback);
var feedback = await resulte.Content.ReadFromJsonAsync<Feedback>();
return feedback;
}
and adapt the calling code accordingly.
I have this http post controller method to insert a new text message to db. Here I want to change this method to async method. I tried but still couldn't do it. Can anyone help me? :)
This is my controller method
[HttpPost]
public ActionResult<Message> Create(Message message)
{
var duplicatemessage = _messageService.DuplicateMessage(message.Text);
if (duplicatemessage == null)
{
_messageService.Create(message);
return CreatedAtRoute("Api", new { id = message.Id.ToString() }, message);
}
else
{
return BadRequest(new { message = "Text Already Exist" });
}
}
These are my service class methods related to the controller post method
public Message DuplicateMessage(string Text)
{
return _messages.Find<Message>(message => message.Text == Text).FirstOrDefault();
}
public Message Create(Message message)
{
_messages.InsertOne(message);
return message;
}
try this:
public async Task<ActionResult<Message>> Create(Message message)
{
var duplicatemessage = await _messageService.DuplicateMessage(message.Text);
if (duplicatemessage == null)
{
_messageService.Create(message);
return CreatedAtRoute("Api", new { id = message.Id.ToString() }, message);
}
else
{
return BadRequest(new { message = "Text Already Exist" });
}
}
public async Task<Message> DuplicateMessage(string Text)
{
return await _messages.Set<Message>().Where(message => message.Text ==
Text).FirstOrDefaultAsync();
}
If you want to implement the async method into your controller (i assume this is what you want). You must first make the function, DuplicateMessage or async. You can do that by making the return type a task and running it in a task.
I have the following code section in which SavePersonAsync method were calling 3 external methods and could anyone tell me the implementation of async/await methods were implemented correctly. Does any of the call chains in which async/await was not implemented correctly?
public PersonService(IPersonDbService personDbService,
IPersonEntityToPersonModelMapper personEntityToPersonModelMapper,
IPersonModelToPersonEntityMapper personModelToPersonEntityMapper)
{
_personDbService = personDbService;
_personEntityToPersonModelMapper = personEntityToPersonModelMapper;
_personModelToPersonEntityMapper = personModelToPersonEntityMapper;
}
public async Task<IEnumerable<PersonModel>> SavePersonAsync(IEnumerable<PersonModel> personsModel)
{
var personsEntity = await _personModelToPersonEntityMapper.MapPersonModelToPersonEntityAsync(personsModel);
var savedPersons = await _personDbService.SavePersonAsync(personsEntity.First()); // Currently only alow one person at a time, later it will allow to save a collection of persons
return await _personEntityToPersonModelMapper.MapPersonEntityToPersonModelyAsync(new List<PersonEntity>
{
savedPersons
});
}
}
public class PersonEntityToPersonModelMapper : IPersonEntityToPersonModelMapper
{
public async Task<IEnumerable<PersonModel>> MapPersonEntityToPersonModelyAsync(
IEnumerable<PersonEntity> personsEntity)
{
if (personsEntity.NullOrEmpty())
return await Task.FromResult(Enumerable.Empty<PersonModel>());
return await Task.FromResult(personsEntity.Select(personEntity => new PersonModel
{
FirstName = personEntity.FirstName,
LastName = personEntity.LastName
}));
}
}
public class PersonModelToPersonEntityMapper : IPersonModelToPersonEntityMapper
{
public async Task<IEnumerable<PersonEntity>> MapPersonModelToPersonEntityAsync(IEnumerable<PersonModel> personsModel)
{
if (personsModel.NullOrEmpty())
return await Task.FromResult(Enumerable.Empty<PersonEntity>());
return await Task.FromResult(personsModel.Select(personModel => new PersonEntity
{
FirstName = personModel.FirstName,
LastName = personModel.LastName
}));
}
}
From the definition of async await when you have written await the flow will start sequential, As you need the output to be used in the next statement then there is not much use of async await in your case
To breief about how it works
Suppose you have to method call which can work async in that can your code would be like:
Var a = GetMethodA();
Var b = GetMethodB();
await a;
await b;
In this case your method will work asynchronous
I'am trying to run my Controller Action in async way.
How do I use async Task ? Or How to run in async way
// Db context
public class DeptContext : DbContext
{
public LagerContext(DbContextOptions<LagerContext> options)
: base(options)
{
Database.Migrate();
}
public DbSet<Department> Departments { get; set; }
public DbSet<Product> Products { get; set; }
}
// This is my Interface IDepRepository
Task<Department> GetDepartmentWithOrWithoutProducts(int deptId, bool includeProducts);
// And my Repository class DepRepository
public class DepRepository : IDepRepository
{
private DeptContext db;
public DepRepository(DeptContext context)
{
db = context;
}
// I'am geting Department name with products or Without products
public async Task<Department> GetDepartmentWithOrWithoutProducts(int deptId, bool includeProducts)
{
if(includeProductss)
{
return await db.Departments.Include(c => c.Products).Where(s => s.deptId == deptId).SingleAsync();
}
return await db.Departments.Where(s => s.deptId == deptId).SingleAsync();
}
}
So How should I do now in my Controller to do it as async way: I tried as following but I don't know if it's right to do like this following:
I'm not getting any error but I don't if it's right way ...
using System.Threading.Tasks;
using System.Net;
using Microsoft.Data.Entity;
using Microsoft.EntityFrameworkCore;
[Route("api/departments")]
public class DepartmentsController : Controller
{
private IDeptRepository _deptInfoRepository;
public DepartmentsController(IDeptRepository deptInfoRepository)
{
_deptInfoRepository = deptInfoRepository;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetDepatment(int id, bool includeProducts = false)
{
var dept = _deptInfoRepository.GetDepartmentWithOrWithoutProducts(id, includeComputers);
if(dept == null)
{
return BadRequest();
}
if(includeProducts)
{
var depResult = new DepartmentDto() { deptId = dept.deptId, deptName = dept.deptName };
foreach(var department in dept.Products)
{
depResult.Products.Add(new ProductDto() { productId = department.productId, deptId = department.deptId, ProductName = department.ProductName });
}
return Ok(depResult);
}
var departmentWithoutProductResult = new DepartmentsWithoutProductsDto() { DeptId = dept.deptId, DeptName = dept.DeptName};
return Ok(departmentWithoutProductResult);
}
How do I do to get my controller in async way.. I don't know where to put those await and ToListAsync(). Thank you in advance!
The interface should be renamed to better show the intent.
public interface IDepRepository {
Task<Department> GetDepartmentWithOrWithoutProductsAsync(int deptId, bool includeProducts);
//...
}
Which would update the implementation accordingly. Since the method is not actually using anything after the async call then there not really any reason to tag the method as async. Just return the Task.
public Task<Department> GetDepartmentWithOrWithoutProductsAsync(int deptId, bool includeProducts) {
if(includeProductss) {
return db.Departments.Include(c => c.Products).Where(s => s.deptId == deptId).SingleAsync();
}
return db.Departments.Where(s => s.deptId == deptId).SingleAsync();
}
The controller action however needs to await the task and then continue after the task has completed so therefore that method will be tagged with async.
[HttpGet("{id}")]
public async Task<IActionResult> GetDepatment(int id, bool includeProducts = false) {
var dept = await _deptInfoRepository.GetDepartmentWithOrWithoutProductsAsync(id, includeComputers);
if (dept == null) {
return BadRequest();
}
if (includeProducts) {
var depResult = new DepartmentDto() { deptId = dept.deptId, deptName = dept.deptName };
foreach (var department in dept.Products) {
depResult.Products.Add(new ProductDto() {
productId = department.productId,
deptId = department.deptId,
ProductName = department.ProductName
});
}
return Ok(depResult);
}
var departmentWithoutProductResult = new DepartmentsWithoutProductsDto() { DeptId = dept.deptId, DeptName = dept.DeptName};
return Ok(departmentWithoutProductResult);
}
What I can't tell from your code is the datatype of what GetDepartments returns. My guess is that you are using EF Core and GetDepartments returns a DbSet or a LINQ query against a DbSet. If that is the case, then after the line where your depEntities variable is set, that variable points to a deferred object (an expression tree that has not been evaulated yet). Or in other words, the actual query has not been sent to the database yet. When you loop over the depEntities (with your foreach loop), you are causing the actual potentially long-running work to occur (database access). That's what you want to await on. So, yes, you could make an async version of GetDepartments or you could also probably change your code to be:
var depEntities = await _depRepository.GetDepartments().ToListAsync();
The call to ToListAsync will enumerate the deferred object and perform the database access. Your return statement would just return results. Behind the scenes, the method actually returns on your await statement and resumes after the work you're awaiting on completes.
One last note.. any database exceptions will occur at the point where the deferred object is enumerated.
You should not do any await on already-prepared results list. It's already contain required data - what you want to wait to?
You should make new async version of your GetDepartments() method and await while obtaining data from repository:
var depEntities = await _depRepository.GetDepartmentsAsync();