I am developing application in MVC5 and MVCMailer. I am sending email using SendAsync command which always show Status = "WaitingforResponse" and mail is not sent. If I use "Send" command instead, it works fine. Here is my code:
var v = new UserMailer().SendCampaignMail("email_address").SendAsync();
and UserMailer.cs
public virtual MvcMailMessage SendCampaignMail(string Email)
{
try
{
return Populate(x =>
{
x.Subject = "Campaing";
x.ViewName = "PasswordReset";
x.To.Add(Email);
});
}
catch(Exception ex)
{
throw ex;
}
}
Screenshot for response: http://prntscr.com/82yfwq
Thanks for your Help:
Related
public async Task<ObservableCollection<CustomerModel>> GetCustomer(string customerNumber, string department)
{
try
{
progressBar.Visibility = ViewStates.Visible;
progressBar.Progress = 0;
listofItems = new ObservableCollection<CustomerModel>();
string url = _client.BaseAddress + "/getcustomers(Number='" + customerNumber + "',department='" +
department + "')";
var response = await _client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
progressBar.Visibility = ViewStates.Invisible;
progressBar.Progress = 100;
string returnjson = await response.Content.ReadAsStringAsync();
ReplyCustomerModel replyCustomerModel =
JsonConvert.DeserializeObject<ReplyCustomerModel>(returnjson);
if (replyCustomerModel != null)
{
listofItems = replyCustomerModel.Customers;
}
}
else
{
AlertDialog.Builder alertDiag = new AlertDialog.Builder();
alertDiag.SetTitle("Butikscanner App");
alertDiag.SetMessage("User Does not exist");
alertDiag.SetPositiveButton("OK",
(senderAlert, args) => { });
alertDiag.SetNegativeButton("Cancel", (senderAlert, args) => { alertDiag.Dispose(); });
Dialog diag = alertDiag.Create();
diag.Show();
}
return listofItems;
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
Actually that is what i am doing if my response is false i am trying to show alert dialog that user does not exist I am working my project in MVVM light
Actually that is what i am doing if my response is false i am trying to show alert dialog that user does not exist I am working my project in MVVM light
Actually that is what i am doing if my response is false i am trying to show alert dialog that user does not exist I am working my project in MVVM light
Usually, API calls are made in a background thread using async-await if that is the case with you as well then I would suggest that you do is call the dialog's show method on the UIThread. For this, you will need an activity context i.e. An activity's reference.
There are two way for you to do it either directly call this method as an action something like this:
private void ShowDialog()
{
AlertDialog.Builder alertDiag = new AlertDialog.Builder();
alertDiag.SetTitle("Butikscanner App");
alertDiag.SetMessage("User Does not exist");
alertDiag.SetPositiveButton("OK",(senderAlert, args) => { });
alertDiag.SetNegativeButton("Cancel", (senderAlert, args) => { alertDiag.Dispose(); });
Dialog diag = alertDiag.Create();
diag.Show();
}
assuming above is how your method is defined you can run it on UI thread like:
activity.RunOnUIThread(ShowDialog);
But in your scenario, I do not personally think that this is a smart thing to do because the only line of code that is supposed to be on UIThread(at least i think so) is the dialog.Show();
What you should do rather would be use a lamba expression for a anonymous method something like:
private void ShowDialog(Activity activity)
{
AlertDialog.Builder alertDiag = new AlertDialog.Builder();
alertDiag.SetTitle("Butikscanner App");
alertDiag.SetMessage("User Does not exist");
alertDiag.SetPositiveButton("OK",(senderAlert, args) => { });
alertDiag.SetNegativeButton("Cancel", (senderAlert, args) => { alertDiag.Dispose(); });
Dialog diag = alertDiag.Create();
activity.RunOnUIThread(()=>
{diag.Show();});
}
My controller is something like this:
[HttpPost]
[Route("Somewhere")]
public JsonResult SetSomething(string propertyName, string propertyValue)
{
var successSave = this.SaveIt(propertyName,propertyValue);
if(successSave)
return Json(propertyValue);
else
// Show a message in front end that there was problem in saving
}
And then my view is currently something like:
#Model.SomethingFeild
That just loads the value and shows it in a textbox field in there .
So how can I change this to be able to handle the psedo-code scenario I wrote in the controller, so that if something is wrong in DB ( not front-end vlaidation) such as duplicate entry, then it comes back and tells the UI that so UI shows a hard coded message?
Wrap it in try catch block and add an extension method for reading exception (or your exception type that is thrown) like so:
[HttpPost]
[Route("Somewhere")]
public JsonResult SetSomething(string propertyName, string propertyValue)
{
try
{
var successSave = this.SaveIt(propertyName, propertyValue);
if (successSave)
return Json(new { success = true, value = propertyValue });
}
catch (Exception ex)
{
return Extensions.ReturnExceptionToView(ex);
}
}
Example extension method (static method):
internal static JsonResult ReturnExceptionToView(Exception ex)
{
List<object> viewErrors = new List<object>();
viewErrors.Add(new { ErrorMessage = ex.ToString() });
return new JsonResult() { Data = (new { success = false, errors = viewErrors }) };
}
Then check for success property in the response in JS. Example below is using response of ajax call and pushing to Knockout observable array.
if (response.success) {
// do something with successful response
} else {
// we have an error in the response.errors collection
$.each(response.errors, function () {
vm.saveErrors.push(new ErrorMsg(this.ErrorMessage));
});
It was working good, but I made some changes in the api, adding more controllers nothing out of the place, and then it stops working, always thrown an exception: "TaskCanceledException: A task was canceled" in the line GetAsync().result. I increase the timeout and infinitely stays loading.
The code controller APP who make a request to the controller API:
public ActionResult Login(LoginM us)
{
try
{
cuentaM account = new cuentaM();
HttpClient client = new HttpClient();
var result = client.GetAsync("http://localhost:26723/api/Login" + "?email=" + us.email + "&password=" + us.password).Result;
if (result.IsSuccessStatusCode)
{
account = result.Content.ReadAsAsync<cuentaM>().Result;
}
Session["cuenta"] = account;
return RedirectToAction("Index", "Home");
}
catch (Exception ex)
{
throw;
}
}
The controller API code:
public HttpResponseMessage Get(string email, string password)
{
try
{
using (elevationbEntities db = new elevationbEntities())
{
usuario user = db.usuarios.Where(m => m.email == email && m.password == password).SingleOrDefault();
cuentaM account = new cuentaM();
if (user != null)
{
account = (from o in db.cuentas
join cu in db.cuentausuarios on o.idCuenta equals cu.idCuenta
join u in db.usuarios on cu.idUsuario equals u.idUsuario
where u.idUsuario == user.idUsuario
select new cuentaM { idUsuario = user.idUsuario, idCuenta = o.idCuenta, CodigoUnico = o.CodigoUnico })
.FirstOrDefault();
}
else
{
account.Error = "Wrong Password or Email";
}
HttpResponseMessage response;
response = Request.CreateResponse(HttpStatusCode.OK, account);
return response;
}
}
catch (TaskCanceledException ex)
{
HttpResponseMessage response;
response = Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
return response;
}
}
Making blocking calls (.Result) on HttpClinet's async API can cause deadlocks especially if being used asp.net MVC, which may have async operations being invoked when the blocking call was made.
Make the code async all the way through.
Also try to avoid creating an instance of HttpClient on every request. This can cause sockets to be exhausted.
private static HttpClient client = new HttpClient();
public async Task<ActionResult> Login(LoginM us) {
try {
cuentaM account = new cuentaM();
var url = "http://localhost:26723/api/Login" + "?email=" + us.email + "&password=" + us.password
var result = await client.GetAsync(url);
if (result.IsSuccessStatusCode) {
account = await result.Content.ReadAsAsync<cuentaM>();
}
Session["cuenta"] = account;
return RedirectToAction("Index", "Home");
} catch (Exception ex) {
throw;
}
}
You may be deadlocking by blocking on an async call, as described in this article. Here's the problematic line:
account = result.Content.ReadAsAsync<cuentaM>().Result;
Change the method signature for Login to:
public async Task<ActionResult> Login(LoginM us)
Then change the problematic line to use await instead of .Result:
account = await result.Content.ReadAsAsync<cuentaM>();
See first how i design my web api action.
[System.Web.Http.RoutePrefix("api/Appointments")]
public class AppointmentsServiceController : ApiController
{
[System.Web.Http.HttpGet, System.Web.Http.Route("UserAppointments/{email}")]
public IHttpActionResult UserAppointments(string email)
{
if (!string.IsNullOrEmpty(email))
{
AppointmentsService _appservice = new AppointmentsService();
IEnumerable<Entities.Appointments> app = _appservice.GetUserWiseAppointments(email);
if (app.Count() <= 0)
{
return NotFound();
}
else
{
return Ok(app);
}
}
else
{
return BadRequest();
}
}
}
Now this way i am calling web api action from my asp.net mvc action by HttpClient.
public async Task<ActionResult> List()
{
var fullAddress = ConfigurationManager.AppSettings["baseAddress"] + "api/Appointments/UserAppointments/" + Session["useremail"];
IEnumerable<Entities.Appointments> app = null;
try
{
using (var client = new HttpClient())
{
using (var response = client.GetAsync(fullAddress).Result)
{
if (response.IsSuccessStatusCode)
{
var customerJsonString = await response.Content.ReadAsStringAsync();
app = JsonConvert.DeserializeObject<IEnumerable<Entities.Appointments>>(customerJsonString);
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.Content.ReadAsStringAsync().Result);
//MessageBox.Show(dict["Message"]);
}
}
}
}
catch (HttpRequestException ex)
{
// catch any exception here
}
return View();
}
}
i want capture the return IEnumerable and if not data return that also i have to capture. please show me the right direction.
Where i made the mistake. thanks
Mixing async with blocking calls like .Result
var response = client.GetAsync(fullAddress).Result
And
response.Content.ReadAsStringAsync().Result
can lead to deadlocks, which is possibly why it it not hitting your API.
Refactor the code to be async all the way.
That would mean updating the using to
var response = await client.GetAsync(fullAddress)
and the reading of the content in the else statement to
await response.Content.ReadAsStringAsync()
Reference Async/Await - Best Practices in Asynchronous Programming
It looks like you are not awaiting your GetAsync call, so in the following if (response.IsSuccessStatusCode) is probably always returning false. Try calling your method like this:
using (var response = (await client.GetAsync(fullAddress)).Result)
{
Description :
I'm sending an email from MVC application, mail was sent successfuly when I send it to a single person but when I send mail to multiple people then getting an exception i.e. Operation has timed out.
So, to avoid this problem I'm trying use smtpclient.SendAsync(message,object) method but I'm getting an exception i.e. An asynchronous module or handler completed while an asynchronous operation was still pending.
How to resolve this problem ?
Code:
public async Task<string> SendEmail(List<string> ToEmailAddresses,string body, string emailSubject)
{
var smtp = new SmtpClient
{
DeliveryMethod = SmtpDeliveryMethod.Network,
Host = "xyz-host-name",
Port = 25,
EnableSsl = false,
Timeout = 600000
};
var fromAddress = new MailAddress(ConfigurationManager.AppSettings["MailUserName"], "Rewards and Recognition Team");
using (var message = new MailMessage() { Subject = emailSubject, Body = body })
{
message.From = fromAddress;
foreach (string email in ToEmailAddresses)
{
message.To.Add(email);
}
message.IsBodyHtml = true;
try
{
_logger.Log("EmailService-SendEmail-try");
object userToken = message;
smtp.SendAsync(message,userToken);
return "Success";
}
catch (Exception ex)
{
_logger.Log("EmailService-SendEmail-" + ex.Message);
return "Error";
}
}
}
you have to use the await keyword in actionresult (controller side)
like
public async task<ActionResult> SendMail(object obj)
{
var result = await SendEmail(ToEmailAddresses,body,emailSubject)
return result
}