System.Web.Http.HttpResponseException in catch block while exception handling - c#

I am intentionally making a violation of a unique constraint in my database, and trying to handle an exception.
This among else is in my form:
HttpResponseMessage response = KorisniciService.PostResponse(k);
if (response.IsSuccessStatusCode)
{
MessageBox.Show(Messages.add_usr_succ);
DialogResult = DialogResult.OK;
Close();
}
else
{
string message = response.ReasonPhrase;
if (string.IsNullOrEmpty(Messages.ResourceManager.GetString(response.ReasonPhrase)))
message = Messages.ResourceManager.GetString(response.ReasonPhrase);
MessageBox.Show("Error code: " + response.StatusCode + " Message: " + message);
}
My controller:
public IHttpActionResult PostKorisnici(Korisnici obj)
{
if (!ModelState.IsValid)
return BadRequest();
try
{
obj.KorisnikId = Convert.ToInt32(dm.esp_Korisnici_Insert(obj.Ime, obj.Prezime, obj.Email, obj.Telefon, obj.KorisnickoIme, obj.LozinkaSalt, obj.LozinkaHash, obj.Status, obj.Adresa, obj.GradId).FirstOrDefault());
}
catch (EntityException ex)
{
throw CreateHttpResponseException(Util.ExceptionHandler.HandleException(ex), HttpStatusCode.Conflict);
}
foreach (var item in obj.Uloge)
{
dm.esp_KorisniciUloge_Insert(obj.KorisnikId, item.UlogaId);
}
return CreatedAtRoute("DefaultApi", new { id = obj.KorisnikId }, obj);
}
HttpResponseException making function:
private HttpResponseException CreateHttpResponseException(string reason, HttpStatusCode code)
{
HttpResponseMessage msg = new HttpResponseMessage()
{
StatusCode = code,
ReasonPhrase = reason,
Content = new StringContent(reason)
};
return new HttpResponseException(Request.CreateResponse(msg));
}
Exception handler class:
public class ExceptionHandler
{
public static string HandleException(EntityException error)
{
SqlException ex = error.InnerException as SqlException;
switch (ex.Number)
{
case 2627:
{
return GetConstraintExceptionMessage(ex);
}
default:
return error.Message + "(" + error +")";
}
}
/*Message "Violation of UNIQUE KEY constraint 'CS_KorisnickoIme'. Cannot insert duplicate key in object 'dbo.Korisnici'. The duplicate key value is (farish).\r\nThe statement has been terminated." string*/
private static string GetConstraintExceptionMessage(SqlException error)
{
string newMessage = error.Message;
int startIndex = newMessage.IndexOf("'");
int endIndex = newMessage.IndexOf("'", startIndex + 1);
if (startIndex>0 && endIndex>0)
{
string constraintName = newMessage.Substring(startIndex + 1, endIndex - startIndex - 1);
if (constraintName == "CS_KorisnickoIme")
newMessage = "username_con";
else if (constraintName == "CS_Email")
newMessage = "email_con";
}
return newMessage;
}
So when I produce an error, instead of a popup window (which shows up fine in a tutorial video) I get a System.Web.Http.HttpResponseException in a first catch block of my post method and nothing passed back to my form.

I think because the exception is being thrown and not inside a try/catch block, or the catch block receiving the CreateHttpResponseException, is absorbing it and not providing a response object.
EDIT
Can you post the code for KorisniciService.PostResponse?
and nothing passed back to my form
And what is the eventual result? From the form code you have posted it should either popup message box with success message, or popup message box with fail message. What actually happens?
2nd EDIT
Following further information, use this in your form code...
try
{
HttpResponseMessage response = KorisniciService.PostResponse(k);
if (response.IsSuccessStatusCode)
{
MessageBox.Show(Messages.add_usr_succ);
DialogResult = DialogResult.OK;
Close();
}
}
catch(HttpResponseException ex)
{
string message = ex.ReasonPhrase;
if (string.IsNullOrEmpty(Messages.ResourceManager.GetString(ex.ReasonPhrase)))
message = Messages.ResourceManager.GetString(ex.ReasonPhrase);
MessageBox.Show("Error code: " + ex.StatusCode + " Message: " + message);
}

Related

Error for Xamarin IOS Firebase AuthDataResult does not Contain ProfileChangeRequest()

I'm getting an error saying AuthDataResult does not contain ProfileChangeRequest() when i try to change the name of the user. I've to research online and read the firebase docs as well but no luck.
public static async Task Register(UIViewController thisView,
string inpName,
string inpEmail,
string inpPassword)
{
bool done = false;
AppDataClass.auth.CreateUser(inpEmail, inpPassword, (user, error) =>
{
if (error != null)
{
AlertShow.Alert(thisView, "Error",
"This went wrong: " + error.UserInfo.Description);
return;
}
UserProfileChangeRequest changeReq = user.ProfileChangeRequest;
changeReq.DisplayName = inpName;
changeReq.CommitChanges((profileError) =>
{
if (profileError != null)
{
AlertShow.Alert(thisView, "Error",
"Profile Error: " + profileError);
return;
}
done = true;
});
});
while (!done)
{
await Task.Delay(50);
}
}
If you read the document about method -signInWithEmail:password:completion:, the call back it retures is a FIRAuthDataResultCallback , the first parameter here is FIRAuthDataResult.
So the user should be:
user.user.ProfileChangeRequest
To make it clear:
public static async Task Register(UIViewController thisView,
string inpName,
string inpEmail,
string inpPassword)
{
bool done = false;
AppDataClass.auth.CreateUser(inpEmail, inpPassword, (authDataResult, error) =>
{
if (error != null)
{
AlertShow.Alert(thisView, "Error",
"This went wrong: " + error.UserInfo.Description);
return;
}
UserProfileChangeRequest changeReq = authDataResult.user.ProfileChangeRequest;
changeReq.DisplayName = inpName;
});
while (!done)
{
await Task.Delay(50);
}
}
Refer: ERROR is value of type 'AuthDataResult' has no member 'uid'

Exception Logging Without using try catch - ASP.NET WEB API

I need to log exceptions and bad requests in my API. Currently I am using try catch to catch the exception and add to my logs in the catch block. Is this the right way? I read about Global Error Handling in ASP.NET. How can I implement that approach for this case?
Below is my API Controller example:
[HttpPost]
[Authorize]
[ValidateModel]
[Route("CheckProgramOwner")]
public async Task<IHttpActionResult> CheckProgramOwner([FromBody] CheckProgramOwner _data)
{
try
{
using (var db = new VisualVoiceFlowEntities())
{
var Result= await db.VVF_ScriptFlow.Where(s => s.ProgramId == _data.ProgramId).OrderByDescending(s => s.ID).FirstOrDefaultAsync();
if(Result== null)
{
Log.Error("Error in CheckProgramOwner POST Request - " + "ProgramId not found");
return Content(HttpStatusCode.BadRequest, "ProgramId not found");
}
string CurrentOwner = Result.ReadBy.ToString();
return Ok(CurrentOwner);
}
}
catch (Exception ex)
{
Log.Error("Error in CheckProgramOwner POST Request - " + ex.Message, ex);
NewRelic.Api.Agent.NewRelic.NoticeError("Error in CheckProgramOwner POST Request - " + ex.Message, null);
return Content(HttpStatusCode.InternalServerError, "Internal Server Error. Please Contact Admin.");
}
}
If you read the document previously posted by Casey, you will find a link to the following document, which explains how to implement and register an exception filter globally:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling#registering_exception_filters
You could then implement your logging logic in the filter's body thus avoiding having to repetitively log errors on each try/catch. I would suggest logging the more obvious errors using your original approach and use the filter to log any other errors (that you might not expect.)
I did it using ExceptionFilter.
I created Exception Filter Class as below -
public class MyExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
log4net.ThreadContext.Properties["addr"] = HttpContext.Current.Request.UserHostAddress;
log4net.ThreadContext.Properties["Hostname"] = Dns.GetHostName().ToString();
log4net.ThreadContext.Properties["PCName"] = Dns.GetHostAddresses(Environment.MachineName)[0].ToString();
string RequestMethod = context.Request.Method.Method;
dynamic ControllerInfo = context.ActionContext.ControllerContext.Controller;
string RequestName = ControllerInfo.Url.Request.RequestUri.LocalPath.ToString().Replace("/api/", "").Replace("/VVFAPI", "");
Log.Error("Error in " + RequestName +" "+ RequestMethod+ " Request - " + context.Exception.Message, context.Exception);
NewRelic.Api.Agent.NewRelic.NoticeError("Error in " + RequestName + " " + RequestMethod + " Request - " + context.Exception.Message, null);
HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("Internal Server Error. Please Contact Admin."),
ReasonPhrase = "Critical Exception."
};
context.Response = msg;
}
}
Also, I changed my controller accordingly
[HttpPost]
[Authorize]
[ValidateModel]
[MyExceptionFilter]
[Route("CheckProgramOwner")]
public async Task<IHttpActionResult> CheckProgramOwner([FromBody] CheckProgramOwner _data)
{
Log.Info("CheckProgramOwner POST Request");
using (var db = new VisualVoiceFlowEntities())
{
var Result = await db.VVF_ScriptFlow.Where(s => s.ProgramId == _data.ProgramId).OrderByDescending(s => s.ID).FirstOrDefaultAsync();
if (Result == null)
{
Log.Error("Error in CheckProgramOwner POST Request - " + "ProgramId not found");
return Content(HttpStatusCode.BadRequest, "ProgramId not found");
}
string CurrentOwner = Result.ReadBy.ToString();
return Ok(CurrentOwner);
}
}

Kendo Grid duplication message

I am using Kendo grid and I have stopped the grid from saving duplicate values as follows in create method:
var results = new List<ProviderTypeMasterViewModel>();
try
{
_logger.LogInformation("ProviderTypeMastersController ProviderType_Create Start");
foreach (var ProviderTypeMaster in ProviderTypeMasterList)
{
TblProviderTypeMaster ptm = new ProviderTypeMasterViewModel().ToModel(ProviderTypeMaster);
var provd = _context.TblProviderTypeMasters.Where(p => p.ProviderTypeName == ProviderTypeMaster.ProviderTypeName).ToList();
if (provd != null && provd.Count() == 0)
{
if (ProviderTypeMasterList != null && ModelState.IsValid)
{
string userID = GetUserID();
providerTypeMasterService.SaveProviderTypeMaster(ProviderTypeMaster, userID);
}
}
else
{
duplicate = true;
//Session["ErrMsg"] = "Already Exists";
//return RedirectToAction("ProviderType_Read", "ProviderTypeMasters");
}
}
_logger.LogInformation("ProviderTypeMastersController ProviderType_Create Complete");
}
catch (Exception e)
{
_logger.LogError("ProviderTypeMastersController ProviderType_Create Failed - " + e.Message);
}
return Json(results.ToDataSourceResult(request, ModelState));
And in the read method I have displayed the error message to the user as follows
try
{
if (duplicate == true)
{
TempData["ErroMsg"] = "Already Exists";
}
_logger.LogInformation("In ProviderTypeMastersController ProviderType_Read");
return Json(providerTypeMasterService.ListProviderTypeMaster().ToDataSourceResult(request));
}
catch (Exception e)
{
_logger.LogError("ProviderTypeMastersController ProviderType_Read Failed - " + e.Message);
}
return View();
The duplication process has stopped. But I am unable to show the error message to the user. Can anyone let me know what I should do where I have gone wrong. I have tried using ViewBag,ViewData,TempData.
This is my View
<div>
if (TempData["ErroMsg"] != null)
{
<p>#TempData["ErroMsg"].ToString()</p>
}
you can use DataBinding() and DataBound() function of kendo grid...these functions call in client side after Read method on server side..for example you can set a field and decision with this field

Extract user-friendly error message from entity framework

I have the following code inside my asp.net mvc web application :-
try
{
var count = repository.changeDeviceSwitch(s.Switch.SwitchID, (Int32)s.GeneralSwitchTo, User.Identity.Name.Substring(User.Identity.Name.IndexOf("\\") + 1));
repository.Save();
return Json(new { IsSuccess = "redirect", description = Url.Action("Details", new { id = s.GeneralSwitchTo }) }, JsonRequestBehavior.AllowGet);
}
catch (DbUpdateException exception)
{
return Json(new { IsSuccess = "custome", description = "Error occurred." + exception.InnerException.InnerException.Message.ToString() }, JsonRequestBehavior.AllowGet);
}
catch (Exception e)
{
return Json(new { IsSuccess = "custome", description = "Error occurred." }, JsonRequestBehavior.AllowGet);
}
which will call the following repository method :-
public int changeDeviceSwitch(int fromID , int toID, string username)
{
var currentdevices = tms.TMSSwitchPorts.Where(a => a.SwitchID == fromID);
int count = 0;
foreach (var d in currentdevices)
{
DeletePort(d, username);
//d.SwitchID = toID;
count++;
}
foreach (var d in currentdevices)
{
TMSSwitchPort tsp = new TMSSwitchPort() { SwitchID = toID, TechnologyID = d.TechnologyID, PortNumber = d.PortNumber };
InsertOrUpdatePort(tsp, username);
}
return count;
}
Currently if the DbUpdateException happen the user will get the following information :-
Violation of PRIMARY KEY constraint 'PK_SwitchPortServer'. Cannot
insert duplicate key in object 'dbo.TMSSwitchPorts'. The duplicate key
value is (1484, e). The statement has been terminated.
this exception will happen when the user try to add a port number that already exists under the same record. (SwitchID + Portno) combination are unique inside database. which is purely technical message , so i am not sure if there is a way to extract a more user friendly error message from entity framework? or i need to do the check by myself ?
How about throwing your own exception?
try
{
InsertOrUpdatePort(tsp, username);
}
catch (DbUpdateException e)
{
throw new Exception("Friendly message here", e)
}
Better yet is to define your own exception class to use here, instead of just Exception.

LiveConect Auth (for SkyDrive) NullReferenceException (WTH)?

I followed a 43 minute video tutorial on the Channel 9 site and read the LiveConnect page where it shows code and I don't see what I'm doing wrong. It keeps giving me a NullReferenceException error and it doesn't even bring up the "Do you want to allow app X to access skydrive" thing, it just breaks immediately. I've set breakpoints everywhere but there is nothing. Just null, null everywhere.
OnNavigatedTo event:
LoadProfile();
private async void LoadProfile()
{
try
{
LiveAuthClient auth = new LiveAuthClient();
LiveLoginResult loginResult = await auth.LoginAsync(new string[] { "wl.basic" });
if (loginResult.Status == LiveConnectSessionStatus.Connected)
{
this.pageTitle.Text = "Signed in.";
}
}
catch (LiveAuthException exception)
{
this.pageTitle.Text = "Error signing in: " + exception.Message;
}
}
And the exception says:
I finally found a solution.
Subscribe to a button-click event or whatever, then use this code:
LoadProfile();
which calls this method:
public async void LoadProfile()
{
try
{
LiveAuthClient auth = new LiveAuthClient();
LiveLoginResult initializeResult = await auth.InitializeAsync();
try
{
LiveLoginResult loginResult = await auth.LoginAsync(new string[] { "wl.basic" });
if (loginResult.Status == LiveConnectSessionStatus.Connected)
{
LiveConnectClient connect = new LiveConnectClient(auth.Session);
LiveOperationResult operationResult = await connect.GetAsync("me");
dynamic result = operationResult.Result;
if (result != null)
{
this.pageTitle.Text = string.Join(" ", "Hello", result.name, "!");
}
else
{
this.pageTitle.Text = "Error getting name.";
}
}
}
catch (LiveAuthException exception)
{
this.pageTitle.Text = "Error signing in: " + exception.Message;
}
catch (LiveConnectException exception)
{
this.pageTitle.Text = "Error calling API: " + exception.Message;
}
}
catch (LiveAuthException exception)
{
this.pageTitle.Text = "Error initializing: " + exception.Message;
}
}
Before you debug, add your app to the Windows Store Dashboard. Then go back to Visual Studio, find Package.appxmanifest in Solution Explorer and add the Internet Capability. Then go to the Project menu > Store > Associate App with the Store.
Find your app's name in the list of apps that appears, select it and click Next/Finish and then debug. It should now be working.
Please try this code instead of yours:
LiveAuthClient auth = new LiveAuthClient();
LiveLoginResult loginResult = await auth.InitializeAsync(new string[] { "wl.basic" });
if ( loginResult.Status == LiveConnectSessionStatus.Connected )
{
LiveConnectClient connect = new LiveConnectClient( auth.Session );
...

Categories

Resources