I'm using Hellang ProblemDetails package in a Web API application using .Net Core 5 and I need to log the exception before sending response back to client.
I tried using ExceptionHandler middleware and Hellang ProblemDetails Middleware together, but they didn't work together. How can I log exception globally while using Hellang ProblemDetails?
After some reading, I realized I could't use ExceptionHandler middleware and Hellang ProblemDetails together because both change the response in their own way and affect one another.
Based on the documentation here you can use one of the configuration options of the ProblemDetails package to excute code before changing response and there you can log all the information you need.
services.AddProblemDetails(options =>
{
options.IncludeExceptionDetails = (context, ex) =>
{
var environment = context.RequestServices.GetRequiredService<IWebHostEnvironment>();
return environment.IsDevelopment();
};
options.Map<IdentityException>(exception => new ProblemDetails()
{
Title = exception.Title,
Detail = exception.Detail,
Status = StatusCodes.Status500InternalServerError,
Type = exception.Type,
Instance = exception.ToString()
});
options.OnBeforeWriteDetails = (ctx, pr) =>
{
//here you can do the logging
logger.LogError("Exception Occurred!!!!");
logger.LogError(pr.Detail);
logger.LogError(pr.Instance);
};
});
Here, I use a custom exception with extra fields that are needed for problem details object in response, and I use the Instance field to hold the exception and log all the information I need before returning response back to client.
Another option is to configure options.ShouldLogUnhandledException to cover your cases
https://github.com/khellang/Middleware/blob/5d5257ef54d82c902dbf087486365032d4804aac/src/ProblemDetails/ProblemDetailsMiddleware.cs#L119
Example:
options.ShouldLogUnhandledException = (_, ex, d) => d.Status is null or >= 500 || ex is ValidationException;
I found out that when we enter admin page of my SOLR server there is such a request:
http://localhost:8983/solr/documents/admin/luke?wt=json&show=index&numTerms=0
This request is getting some basic informations about index such as last modified etc. I want to create query using SOLRJ but I can't. My code is very simple:
SolrClient server = new HttpSolrClient("http://localhost:8983/solr/documents/admin");
SolrQuery solrQuery = new SolrQuery("luke?wt=json&show=index&numTerms=0");
QueryResponse response = null;
SolrParams solrParams = solrQuery;
response = server.query(solrParams);
logger.error("PING: " + response.getElapsedTime());
for(SolrDocument doc: response.getResults())
{
for(String key: doc.keySet())
{
logger.error("KEY: "+key+" VAL: "+doc.get(key));
}
}
logger.error("TEST after");
I got error Problem accessing /solr/docs/admin/select wich isn't something strange. Should I use simple GET and parse JSON or there is some other way to use SOLRJ for this one ?
I guess the correct url for accessing the solr end point should be:
SolrClient server = new HttpSolrClient("http://localhost:8983/solr/documents");
Assuming the core name for your solr setup is documents.
The default handler is /select handler.
When executing an ajax call to a WCF on my local IIS it works fine. The json object i send is the following:
var entity = {};
entity.LogicalName = "new_subsidiedossier";
entity.Id = "63772FDA-9B0A-E511-8270-005056B04A46";
entity.Attributes = [
{ key: "new_aantalurenperdeelnemer", value: { __type: "Decimal:http://schemas.microsoft.com/xrm/2011/Contracts", Value: 11.3 } }
];
With the exact same call i just change the url to our production server. It has the same version of the WCF but only on https. This fails with 'Bad Request' and the following description:
The server encountered an error processing the request. The exception message is 'There was an error deserializing the object of type TamSys.Integration.Contract.Models.UpdateRequest. Input string was not in a correct format.'. See server logs for more details. The exception stack trace is:
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver) at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName) at
Anyone experienced this before?
Regards
I'm using the following to read Twitter json. It works with one uri and not another. The uri's work with the Twitter API console but not Xamarin.Social. I have read and write permissions on the Twitter app so I can't see where I'm going wrong.
https://api.twitter.com/1.1/account/settings.json <-- works
https://api.twitter.com/1.1/users/show.json?screen_name=AUserName <-- fails (see error below)
request.GetResponseAsync ().ContinueWith (response => {
if (response.IsFaulted)
{
Console.WriteLine (response.Exception.Flatten ());
}
var json = response.Result.GetResponseText ();
System.AggregateException: One or more errors occured ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult result) [0x0030c] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1606
at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData data) [0x00141] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1423
--- End of inner exception stack trace ---
--> (Inner exception 0) System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult result) [0x0030c] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1606
at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData data) [0x00141] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1423
[quick google search gave this but not sure if its relevant: https://dev.twitter.com/discussions/15206]
// UPDATE ***********
Does this extra infor help or you need more details? If so then what details are required?
public Account Account
{
get
{
var task = Service.GetAccountsAsync ()
.ContinueWith (accounts =>
{
return accounts.Result.ToList ().FirstOrDefault ();
});
return task.Result;
}
set
{
AccountStore.Create ().Save (value, SocialPlatform.ToString ());
}
}
// later on
// when endpoint = "https://api.twitter.com/1.1/account/settings.json" <-- works, json returned
// when endpoint = "https://api.twitter.com/1.1/users/show.json?screen_name=XXXX" <-- IsFaulted with above error,
var request = Service.CreateRequest ("GET", endpoint, Account);
request.GetResponseAsync ().ContinueWith (response => {
if (response.IsFaulted)
{
Console.WriteLine (response.Exception.Flatten ());
return;
}
var json = response.Result.GetResponseText ();
Console.WriteLine (json);
});
It seems like you are not authorised when you make this call.
From Xamarin.Social documentation.
Xamarin.Social uses the Xamarin.Auth library to fetch and store
Account objects.
Each service exposes a GetAuthenticateUI method that returns a
Xamarin.Auth.Authenticator object that you can use to authenticate the
user. Doing so will automatically store the authenticated account so
that it can be used later.
The reason why it works in Twitter API console is that you have authorised there prior to making a call.
If you are already authorising in your app then please post the code you use to authorise.
So i am making some ajax post and it seems to work fine on the localhost, but when I publish it to ec2 server on amazon, I get Uncaught SyntaxError: Unexpected token B. Which seems to point to JSON parsing failure. Exact same database, same browser, and same methods being called. Why would it work on local and not on the server.
$.ajax({
url: '#Url.Action("Action")',
type: "POST",
data: ko.toJSON(viewModel),
dataType: "json",
contentType: "application/json; charset:utf-8",
success: function (result) {
},
error: function (xhr, textStatus, errorThrown) {
var errorData = $.parseJSON(xhr.responseText);
var errorMessages = [];
for (var key in errorData)
{
errorMessages.push(errorData[key]);
}
toastr.error(errorMessages.join("<br />"), 'Uh oh');
}
});
Here is the basic layout on the server side:
[HttpPost]
public JsonResult Action(ViewModel model)
{
try
{
Response.StatusCode = (int)HttpStatusCode.OK;
return Json("Successfull");
}
catch (Exception ex)
{
logger.Log(LogLevel.Error, string.Format("{0} \n {1}", ex.Message, ex.StackTrace));
Response.StatusCode = (int)HttpStatusCode.BadRequest;
List<string> errors = new List<string>();
errors.Add(ex.Message);
return Json(errors);
}
}
Within the try statement, I do a couple of queries to the database and post some calculations on Authorize.Net (https://api.authorize.net/soap/v1/Service.asmx)
If there are any error with Authorize.net web service calls then I return errors like this:
if (profile.resultCode == MessageTypeEnum.Error)
{
logger.Log(LogLevel.Error, string.Join(",", profile.messages.Select(x => x.text)));
Response.StatusCode = (int)HttpStatusCode.BadRequest;
List<string> errors = new List<string>();
profile.messages.ToList().ForEach(x => errors.Add(x.text));
db.SaveChanges();
return Json(errors);
}
This error that I am logging:
A public action method 'AddPromoCode' was not found on controller 'Flazingo.Controllers.PositionController'. at
System.Web.Mvc.Controller.HandleUnknownAction(String actionName) at
System.Web.Mvc.Controller.ExecuteCore() at
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) at
System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.b__5() at
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.b__0() at
System.Web.Mvc.MvcHandler.<>c__DisplayClasse.b__d() at
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&
completedSynchronously)
You have another post at can't find action only on live server, works fine in local server, so I'm guessing that this post is specifically related to the javascript pieces, not the server-side pieces.
It sounds like something bad happens on the server, the server sends back some type of error, and the your error handler (in javascript) dies when trying to handle that response.
I get Uncaught SyntaxError: Unexpected token B. Which seems to point
to JSON parsing failure.
That sounds quite reasonable. Let's look at the code:
.ajax({
...
error: function (xhr, textStatus, errorThrown) {
var errorData = $.parseJSON(xhr.responseText);
var errorMessages = [];
...
},
...
});
I would highly recommend taking a look at what xhr.responseText is. My guess it that it does not contain valid JSON, so the parseJSON method throws the 'Unexpected token B' error.
To look at this value, you could put console.log(xhr.responseText); or you could use a tool like the javascript debugger in your web browser or fiddler to see what is there.
My guess is that the server is sending back a string with something like There was an error on the server instead of JSON like you are expecting. I see that you have error handling built in - my guess is that there is an error within your error handling, and there is nothing to catch it. I would recommend doing debugging on the server side to see if there is an error somewhere that you are not expecting.
Perhaps profile.messages is something that can only be enumerated once, and when you try to do it again it throws an error. Or maybe DB.SaveChanges is throwing an error for some reason. Either of these would result in the logged message that you see with the behavior you see on the client side.
You are attempting to return a 400 response (Bad Request) with your own custom response content.
I think that IIS by default doesn't allow you to do this, and as CodeThug mentioned, may be replacing your custom JSON content with a server message.
But it appears that you can override this behaviour:
http://develoq.net/2011/returning-a-body-content-with-400-http-status-code/
<system.webServer>
<httpErrors existingResponse="PassThrough"></httpErrors>
</system.webServer>
I have received similar mysterious errors in the past when using ASP.NET script bundling on knockout and bootstrap, especially when including the already-minified versions in a bundle.
If you are running in DEBUG mode on localhost, then ASP.NET will not be minifying the javascript libraries. However, once you deploy, you are presumably no longer in DEBUG mode and now minifying/bundling the scripts. Sometimes the bundling/minification of these scripts can result in syntax errors similar to the one you posted.
If so, you may be able to load knockout from a CDN to avoid the need for bundling.
It seems JSON sending as the response from the server is badly generated
ex: if a value in the database is hi "my" friends
JSON file will be generated as text:"hi "my" friends"
so value for property text is badly generated.
double check values in production/development server for such values.
best practice is replace quotes with escape character
ex: text:"hi \"my\" friends"