How do I get the error message from BadRequestErrorMessageResult? - c#

Well, the question is simple as you might seen. I need to get the error message from IHttpActionResult method, which returns BadRequest. See the example:
public async Task<IHttpActionResult> SomeMethod(string data) {
if (data==null) return BadRequest("Error messsage for you");
}
string data;
var result = await SomeMethod(data = null);
if (result is BadRequestErrorMessageResult) string error = result.ErrorMessageINeeded;
So, how do I get this one? Is there a class, which receives result object as a parameter and gets the error message from him? any ideas?
For somehow Message property is unavailable in result

if (result is BadRequestErrorMessageResult errorResult)
{
string error = errorResult.Message;
}
or, for C# versions older then 7.0:
if (result is BadRequestErrorMessageResult)
{
string error = ((BadRequestErrorMessageResult)result).Message;
}

Related

how to pass an error message back before an exception is thrown

i have the following code that gets an error message.i want to pass it into a string before an exception is thrown,this is my code
ValidateError(authDeserialized, "Succeed", "error", "failed"); //the validateError is a function as indicated below
Model.Response= authResponse.Content;
protected static void ValidateError(dynamic response, string validStatus,string categoryMatch, string message)
{
if (response.result.status != validStatus)
{
try
{
var category = response.result.category;
if (category == categoryMatch)
message=ErrorCodes.MessageFor(code,description);
//so i get the message back fine here but now how do i pass it back to this line Model.Response= authResponse.Content; so that it can get saved?
}
catch (Exception) { }
throw new Exception(message ?? "Request was not successfull");
}
}
As you are already sending message to the ValidateError() method, pass that parameter as a out parameter, it will update value of message if you assign new value to it then it will update message and will be accessible to outside environment.
string failureMessage = "failed";
ValidateError(authDeserialized, "Succeed", "error", out failureMessage);
//^^^ This is what you have to change
//Now you can assign failureMessage to any other value
Model.Response= authResponse.Content;
protected static void ValidateError(dynamic response, string validStatus,string categoryMatch, out string message)
{ //^^^ This is what you have to change
if (response.result.status != validStatus)
{
try
{
var category = response.result.category;
if (category == categoryMatch)
message=ErrorCodes.MessageFor(code,description); //so i get the message back fine here but now how do i pass it back to this line Model.Response= authResponse.Content; so that it can get saved?
}
catch (Exception) { }
throw new Exception(message ?? "Request was not successfull");
}
}
In this way you can assign value to failure message before throwing an error.
Try out online

Why is my class object empty after running JsonConvert.DeserializeObject<class>(string)?

I am trying to deserialize a JSON string into a large object; I'm using Angular to send my data to a controller. Data is present and correct when it arrives in the controller, but after deserialization, it's null. I've looked at some questions already, like this one here:
Deserialization of JSON.Net returns 'null'
Based on the answer to the question above, and the comment from the user who wrote the question, my code should work, but it doesn't.
Here's my code:
[HttpPost]
public OnlineOrderValidation Post(HttpRequestMessage request)
{
Task<string> result = request.Content.ReadAsStringAsync();
var json = result.Result;
OnlineOrder order = new OnlineOrder();
order = JsonConvert.DeserializeObject<OnlineOrder>(json);
// Save first
_orderFacade.UpdateCurrentOrder(CacheStore, order);
var validation = _orderFacade.ValidateOrder(order);
return validation;
}
The OnlineOrder class should accept all of the data from JsonConvert.DeserializeObject(json), but the values are either 0, null, or false.
I've tried DeserializeAnonymousType(string json, T anonObject) and JavasScriptSerializer.Deserialize(string data) as well, and they both yield an empty OnlineOrder object with null values.
I've also tried passing the object to the controller like this:
public OnlineOrderValidation Post([FromBody]string ooJson)
{
var order = JsonConvert.DeserializeObject<OnlineOrder>(ooJson);
//work with order object...
}
and like this
public OnlineOrderValidation Post([FromUri]string ooJson)
{
var order = JsonConvert.DeserializeObject<OnlineOrder>(ooJson);
//work with order object...
}
I wonder if the problem lies with 'ReadAsStringAsync()'. I noticed that it spits out each property on OnlineOrder out of order. The async part of this method must add each field/value pair as it finishes parsing the string, and since the first field in result doesn't match the first field on the OnlineOrder object, maybe JsonConvert.DeserializeObject() just stops execution.
Do I need to make a wrapper class for OnlineOrder and deserialize to that? Do I need to reorder the fields in my 'result' object before deserializing? Is there something else I'm doing wrong? Thanks all!
EDIT: Here is my JSON, as requested. The actual object is much larger than this, but you get the idea. The JSON string has valid data, but is either nulled or zeroed out after deserialization.
{"isTMIOfferEligible":false,
"tmiOfferCode":null,
"tmiUpgradeOfferCode":null,
"id":"a34mdxdivt0svmu1okucidbi",
"accountNumber":"111111111",
"transferAccountNumber":"222222222",
"serviceAddress":
{"address":"3922 N STREET AVE",
"addressLine":"3901 N STREET AVE",
"suite":"SYNCRD",
"city":"SOOFOO",
"state":"SD",
"zip":"57000",
"franchise":"111",
"market":"1 "},
"transferAddress":
{"disconnectDate":null,
"transferFromAddress":
{"address":"1234 SOME PLACE",
"addressLine":"1234 SOME PLACE",
"suite":"SYNCRD",
"city":"SOOFOO",
"state":"SD",
"zip":"57000",
"franchise":"123",
"market":"Z "
}
}
}
EDIT 2
I've updated my code to deserialize the JSON string from a custom, async method, and instantiate OnlineOrder when it's assigned:
try
{
var orderTask = ReadStringAsynchronously(request);
OnlineOrder order = orderTask.Result;
//work with order object
}
catch (Exception ex) { //...}
private async Task<OnlineOrder> ReadStringAsynchronously(HttpRequestMessage request)
{
try
{
var json = await request.Content.ReadAsStringAsync();
OnlineOrder orderAsync = JsonConvert.DeserializeObject<OnlineOrder>(json);
return orderAsync;
}
catch (Exception)
{
throw new Exception("Error occurred while reading string asynchronously.");
}
}
The order object on the task is still null.
The issue, in this case, was in the JSON string itself. There was HTML nestled within the JSON string that was not being encoded. Before posting to the server, I used encodeURIComponent(value) in a custom method:
function encodeOrderHtml(order) {
debugger;
var o = order;
//scrub HTML from product options
if (o && o.serviceDiscount) {
var sd = o.serviceDiscount;
if (sd.description !== "" && sd.description !== null) {
sd.description = encodeURIComponent(sd.description);
}
if (sd.descriptionNew !== "" && sd.descriptionNew !== null) {
sd.descriptionNew = encodeURIComponent(sd.descriptionNew);
}
if (sd.displayNameNew !== "" && sd.displayNameNew !== null) {
sd.displayNameNew = encodeURIComponent(sd.displayNameNew);
}
if (sd.name !== "" && sd.name !== null) {
sd.name = encodeURIComponent(sd.name);
}
}
return o;
}
I was able to get valid data to the server by posting the object in the body of the request.

Update UI using partial view in response of Task Run (Async)

I am working on MVC C# Razor Framework 4.6.
I have static method ExportManager.ExportExcelCannedReportPPR wrapped up in Task.Run for long running report. This method returns boolean value and based on that I am refreshing partial view (_NotificationPanel).
public ActionResult ExportCannedReport(string cannedReportKey, string cannedReportName)
{
string memberKeys = _curUser.SecurityInfo.AccessibleFacilities_MemberKeys; //ToDo: Make sure this is fine or need to pass just self member?
string memberIds = _curUser.SecurityInfo.AccessibleFacilities_MemberIDs; //ToDo: Make sure this is fine or need to pass just self member?
string curMemberNameFormatted = _curUser.FacilityInfo.FacilityName.Replace(" ", string.Empty);
string cannedReportNameFormatted = cannedReportName.Replace(" ", string.Empty);
string fileName = string.Concat(cannedReportNameFormatted, "_", DateTime.Now.ToString("yyyyMMdd"), "_", curMemberNameFormatted);
//ToDo: Make sure below getting userId is correct
string userId = ((_curUser.IsECRIStaff.HasValue && _curUser.IsECRIStaff.Value) ? _curUser.MembersiteUsername : _curUser.PGUserName);
var returnTask = Task.Run<bool>(() => ExportManager.ExportExcelCannedReportPPR(cannedReportKey, cannedReportName, fileName, memberIds, userId));
returnTask.ContinueWith((antecedent) =>
{
if (antecedent.Result == true)
{
return PartialView("_NotificationPanel", "New file(s) added in 'Download Manager'.");
}
else
{
return PartialView("_NotificationPanel", "An error occurred while generating the report.");
}
}, TaskContinuationOptions.OnlyOnRanToCompletion);
return PartialView("_NotificationPanel", "");
}
Now issue is that UI could not get refresh even though _NotificationPanel in ContinueWith get executed.
The issue is that once you return from it - that request is done. You cannot return from it multiple times for a single request. The request and response are a 1-to-1. You need to use async and await here, such that when the export is done then and only then return a result.
public async Task<ActionResult> ExportCannedReport(string cannedReportKey,
string cannedReportName)
{
// Omitted for brevity...
var result =
await Task.Run<bool>(() =>
ExportManager.ExportExcelCannedReportPPR(cannedReportKey,
cannedReportName,
fileName,
memberIds,
userId));
return PartialView("_NotificationPanel",
result
? "New file(s) added in 'Download Manager'."
: "An error occurred while generating the report.");
}
You need to make the method Task returning such that it is "awaitable". Then you mark the method as async which enables the await keyword. Finally, you're ready to execute the long running task and from the result correctly determine and return the desired partial view update.
Update
Alternatively, you could utilize an AJAX call on the client and update once the server responds. For details on that specifically checkout MSDN.

How to collect errors from different functions?

I am doing a project on C#. It's a project to send message using GSM Modem. In my project, I have several function that may give errors. I have used a string variable to store error message. The basic flow is like this.
class SMS{
string message;
public string getport(){
if(ErrorCondition)
message="Error Finding port";
return port;
}
public void executecommand(command){
if(ErrorCondition1)
message="Error Executing Command";
else(ErrorCondition2)
message="No Response from device";
}
public void sendMessage(int number, string text, out string error){
findport();
executecommand(command);
error = message;
}
}
NB:This is not the working code
This is the way I have thought to collect error message, but I not sure if I am doing it the right way. I need your help on this. Is there a better approach? Error string does not save any string.
Update: As the answers of Exception are coming, I am confused about arrangement of try catch, here I have my actual code so that I'll help to give further suggestions.
public string ReadResponse(SerialPort port, int timeout)
{
string buffer = string.Empty;
try
{
do
{
if (receiveNow.WaitOne(timeout, false))
{
string t = port.ReadExisting();
buffer += t;
}
else
{
if (buffer.Length > 0)
message = "Response incomplete";
else
message = "Error on Modem";
}
}
while (!buffer.EndsWith("\r\nOK\r\n") && !buffer.EndsWith("\r\n> ") && !buffer.EndsWith("\r\nERROR\r\n"));
}
catch (Exception ex)
{
throw ex;
}
return buffer;
}
Your (pseudo) code can be refactored to use the de facto way of managing errors in C#, which are exceptions. Based on your code right there, you're used to using a special variable or return value as an error message and there's nothing wrong with that, it just won't be what other C# developers would expect.
Here's some (pseudo) code that demonstrates what I'm typing about.
class SMS {
public string GetPort() {
if (ErrorCondition) {
throw new PortNotFoundException("Error finding port.");
}
return port;
}
public void ExecuteCommand(Command command) {
if(ErrorCondition1) {
throw new UnknownErrorException("Error Executing Command");
}
else(ErrorCondition2) {
throw new NoResponseException("No Response from device");
}
}
public void SendMessage(int number, string text) {
FindPort();
ExecuteCommand(command);
}
}
You'll note that there's no out variable in SendMessage to handle passing out the error to calling code. That's handled by the thrown exceptions. The calling code is at liberty to determine how best to handle the exception.
You can declare
string message;
to
private List<string> message;
and add message to list, will help to catch multiple errors as well. Also make it private so that other class cant access the same.

RestSharp unable to cast object when awaiting for response

Using RestSharp I'm building an API to perform CRUD operations given a datatype/object.
My CrudAbstract class is generic and has the following:
public virtual async Task<keyType> Post(dto item)
{
try
{
var request = await _client.GetRequestAsync(_path);
request.Method = RestSharp.Method.POST;
request.AddJsonBody(item);
var result = await _client.ExecuteRequestAsync<keyType>(request);
return result;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
throw new Exception("Was not able to process crud post operation.");
}
My WebClient class has the following:
Entities = new CrudAbstract<DtoEntity, int>("/entities", this); // in constructor
// So the keyType from definition above is int (Int32)
The post method in this class is
public async Task<T> ExecuteRequestAsync<T>(IRestRequest request)
{
try
{
var response = await GetClient().ExecuteTaskAsync<T>(request);
// Exception occurs here. The above statement is unable to finish.
var data = response.Data;
return data;
}
catch (Exception e)
{
// Log exception
}
throw new Exception("Was not able to process restclient execute async method.");
}
My Api EntitiesController has the following:
public int Post(DtoEntity value)
{
using (var db = // some database...)
{
try
{
// Upsert object into database here
//... value.Id no longer null at this point
/*
The problem occurs here. I only want to return the ID of the object
(value.Id). I do not want to return the whole object (value)
*/
return value.Id;
}
catch (Exception e)
{
// Log exception
}
}
throw new Exception("Was not able to process entities post method.");
}
The exception I get is:
Unable to cast object of type 'System.Int64' to type
'System.Collections.Generic.IDictionary`2[System.String,System.Object]'.
This is basically saying it is unable to cast the object int (which I have returned in the post with value.Id) to a DtoEntity object (which is the actual object on which CRUD operations were performed).
What am I doing wrong?
I have placed typeof and .getType() onto each keyType, T, and value.Id, and all of them are Int32. Is it in the RestSharp library that the problem occurs? At what stage is there a casting of int to a DtoEntity in the line:
var response = await GetClient().ExecuteTaskAsync<T>(request);
Note: when I change the return type of the post method in my controller to DtoEntity and change the value.Id to just value it works. The response is received, and the response.Data is the DtoEntity object.
I've seen similar questions here but not found a solution yet.
I believe you've spotted a bug in RestSharp. RestSharp internally uses a JSON parser called SimpleJson (borrowed from the Facebook .NET SDK). It appears that this parser is correctly deserializing the response body to a number (since JSON is untyped it uses Int64 to be safe), but the RestSharp's JsonDeserializer class attempts to cast this result to an IDictionary in the first line of this method:
private object FindRoot(string content)
{
var data = (IDictionary<string, object>)SimpleJson.DeserializeObject(content);
if (RootElement.HasValue() && data.ContainsKey(RootElement))
{
return data[RootElement];
}
return data;
}
I think your options are:
File an issue with the RestSharp team.
Get the raw string body and cast it to an int yourself (may be the path of least resistance).
Try a different library.

Categories

Resources