I am testing a custom error page with IExceptionHandlerPathFeature (see test code in "CODE SEGMENT" section). In the stack trace, I can see the code line number where the exception was triggered.
I would like to know how to extract the line number from the stack trace without having to parse the large block of text. What methods I could use to get the line number?
TEST ENVIRONMENT
App Type: ASP .NET 6 with Razor pages
IDE: VS 2022
Dev Machine: Windows 11
CODE SEGMENT
public class ErrorHandlerModel : PageModel
{
private string _envName;
public ExceptionDetailsModel ExceptionInfo { get; set; }
public ErrorHandlerModel(IWebHostEnvironment webEnv)
{
_envName = webEnv.EnvironmentName;
}
public IActionResult OnGet()
{
var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionFeature != null)
{
string reqId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
ExceptionInfo = new ExceptionDetailsModel(reqId);
if (HttpContext.Response.StatusCode != 0)
ExceptionInfo.HttpStatus = HttpContext.Response.StatusCode.ToString();
ExceptionInfo.ErrorMessage = exceptionFeature.Error.Message;
ExceptionInfo.StackTrace = exceptionFeature.Error.StackTrace.ToString();
ExceptionInfo.Route = exceptionFeature.Path;
}
if (_envName.ToLower().IndexOf("develop") >= 0)
{
TempData["show_error_details"] = "yes";
}
else
{
TempData["show_error_details"] = "no";
}
return Page();
}
}
Related
I am running dotnet core 2.* and as the title mentions I have trouble getting my try catch to work when calling from API. And before anyone comments I am also running middle-ware to catch any exceptions. It too doesn't perform as expected
Addinional Information:
The Two Classes are in different namespaces/projects
Queries.Authentication is static.
They are both in the same solution
Controller:
[AllowAnonymous]
[HttpPost]
public string Login([FromBody] AuthRequest req)
{
// See if the user exists
if (Authenticate(req.username, req.password))
{
try {
// Should Fail Below
UserDetails ud = Queries.Authentication.GetUser(req.username);
} catch (RetrievalException e){ }
catch (Exception e){ } // Exception Still Comes Through
}
}
Queries.Authentication.GetUser Code:
public static class Authentication {
public static UserDetails GetUser (string username)
{
// Some Code
if (details.success)
{
// Some Code
}
else
{
throw new RetrievalException(details.errorMessage); // This is not caught propperly
}
}
}
Retrieval Exception:
public class RetrievalException : Exception
{
public RetrievalException()
{
}
public RetrievalException(String message)
: base(message)
{
}
public RetrievalException(String message, Exception inner)
: base(message, inner)
{
}
}
EDIT: Adding Middleware Code Here as per request:
public class CustomExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
HttpStatusCode status = HttpStatusCode.InternalServerError;
String message = String.Empty;
var exceptionType = context.Exception.GetType();
if (exceptionType == typeof(UnauthorizedAccessException))
{
message = "Unauthorized Access";
status = HttpStatusCode.Unauthorized;
}
else if (exceptionType == typeof(NullReferenceException))
{
message = "Null Reference Exception";
status = HttpStatusCode.InternalServerError;
}
else if (exceptionType == typeof(NotImplementedException))
{
message = "A server error occurred.";
status = HttpStatusCode.NotImplemented;
}
else if (exceptionType == typeof(RSClientCore.RetrievalException))
{
message = " The User could not be found.";
status = HttpStatusCode.NotFound;
}
else
{
message = context.Exception.Message;
status = HttpStatusCode.NotFound;
}
context.ExceptionHandled = true;
HttpResponse response = context.HttpContext.Response;
response.StatusCode = (int)status;
response.ContentType = "application/json";
var err = "{\"message\":\"" + message + "\",\"code\" :\""+ (int)status + "\"}";
response.WriteAsync(err);
}
}
App Config:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} else
{
app.UseExceptionHandler();
}
...
}
Service Config:
public void ConfigureServices(IServiceCollection services)
{
// Add Model View Controller Support
services.AddMvc( config =>
config.Filters.Add(typeof (CustomExceptionFilter))
);
UPDATE: After playing around with it I noticed that even though my program throws the exception, if I press continue the API controller then handles it as if the exception was never thrown (as in it catches it and does what I want). So I turned off the break on Exception setting, this fixed it in debugger mode. However this the break doesn't seem to be an issue when I build/publish the program. This makes me think it is definitely a issue with visual studio itself rather than the code.
When you set ExceptionHandled to true that means you have handled the exception and there is kind of no error anymore. So try to set it to false.
context.ExceptionHandled = false;
I agree it looks a bit confusing, but should do the trick you need.
Relevant notes:
For those who deal with different MVC and API controller make sure you implemented appropriate IExceptionFilter as there are two of them - System.Web.Mvc.IExceptionFilter (for MVC) and System.Web.Http.Filters.IExceptionFilter (for API).
There is a nice article about Error Handling and ExceptionFilter Dependency Injection for ASP.NET Core APIs you could use as a guide for implementing exception filters.
Also have a look at documentation: Filters in ASP.NET Core (note selector above the left page menu to select ASP.NET Core 1.0, ASP.NET Core 1.1,ASP.NET Core 2.0, or ASP.NET Core 2.1 RC1). It has many important notes and explanations why it works as it does.
Lately I've been trying to get some data from an external source in the form of JSON.
The library I'm using is the unity fork of Newtonsoft.Json. When i run the project on my computer, it pulls data from the external source, and converts it to an object. The UI/text elements I've made should show the data pulled from my external source, when I run the project on my main computer it has no problems and the data shows up no problem, but when i send the project to my Hololens, my debugger gets data and i can literally see data is being pulled from the external source, but the data won't show up on the hololens. Can anyone enlighten me how i can fix this?
My code is as following:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//using SimpleJSON;
using Newtonsoft.Json;
[System.Serializable]
public class TimeProperties
{
public string Year { get; set; }
public string Month { get; set; }
public string Day { get; set; }
public string Hour { get; set; }
public string Minutes { get; set; }
public string Seconds { get; set; }
}
[System.Serializable]
public class TimeClass
{
public TimeProperties Time { get; set; }
}
public class test : MonoBehaviour
{
string url = "http://172.16.24.135:8080";
public Text year;
public Text month;
public Text day;
public Text hour;
public Text minutes;
public Text seconds;
private void Start()
{
StartCoroutine(UpdateValues());
}
IEnumerator PullJsonData()
{
Debug.Log("entered");
WWW www = new WWW(url);
yield return www;
if(www.error != null)
{
print("There was an error getting the data: " + www.error);
yield break;
}
string jsonstring = www.text;
var data = JsonConvert.DeserializeObject<TimeClass>(jsonstring);
Debug.Log(data.Time.Seconds);
var jaren = data.Time.Year; //data["Year"].AsInt;
var maanden = data.Time.Month;//data["Month"].AsInt;
var dagen = data.Time.Day;//data["Day"].AsInt;
var uren = data.Time.Hour;//data["Hour"].AsInt;
var minuten = data.Time.Minutes;//data["Minutes"].AsInt;
var seconden = data.Time.Seconds;//data["Seconds"].AsInt;
year.text = "Year: " + jaren;
month.text = "Month: " + maanden;
day.text = "Days: " + dagen;
hour.text = "Hours: " + uren;
minutes.text = "Minutes: " + minuten;
seconds.text = "Seconds: " + seconden;
}
IEnumerator UpdateValues()
{
while (true)
{
StartCoroutine(PullJsonData());
yield return new WaitForSeconds(1);
}
}
}
I send it to my hololens via Visual studio code 2017 using "Release x86". I also get the following error:
(Filename: 'C:\buildslave\unity\build\artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
Display is Transparent
(Filename: C:\buildslave\unity\build\artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
There was an error getting the data:
(Filename: C:\buildslave\unity\build\artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
Failed to get spatial stage statics - can't retrieve or interact with boundaries! Error code: '0x80040154'.
(Filename: C:\buildslave\unity\build\Runtime/VR/HoloLens/StageRoot.cpp Line: 20)
entered
(Filename: C:\buildslave\unity\build\artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)'
I pull my JSON data from my external source every second, so every second after runtime, this shows up in my debug:
entered(this is a debug.log inside the class pulljsondata()).
There was an error getting the data:
(Filename: C:\buildslave\unity\build\artifacts/generated/Metro/runtime/DebugBindings.gen.cpp Line: 51)
I managed to get everything working. The reason nothing showed up on my UI was because i had Unity 2017.3f1 installed with Hololens toolkit with the MixedRealityToolkit v2017.2.1.2 from github(https://github.com/Microsoft/MixedRealityToolkit-Unity).
How I managed to get it working?
I removed Unity 2017.3f1 and installed Unity 2017.2.1f1 and installed the latest version of the MixedRealityToolkit, v2017.2.1.3.
After reinstalling, I tried getting a canvas with some elements up and running, and it pulled json data from an external URL correctly.
I'm converting junit reports generated by testng to some other format.
I've written this code to do so:
#AfterTest
public void execute()
{
String junitReport = "TEST-"+this.getClass().getCanonicalName()+".xml";
TestManagerLogger obj = new TestManagerLogger();
obj.convertLog(junitReport);
}
But this doesn't work as reports are not generated before the execution of this method.
Is there any way by which this method can be called only after report generation?
My test Case :
#Test(dataProvider = "jobCount")
public void testJobCount(String Scenario, String URL,String methodType, String status) {
URL = URL.replaceFirst("ip", ip);
String logonToken=LogonUtility.logon();
String result= ResponseGenerator.response(URL, logonToken, methodType);
List<HashMap> valuesFromExcel = StringSplitter.getKeyValuePairs(status);// Returns hashmap containing key values ex: failed =0 , total =3
List<HashMap> valuesFromRest = new ArrayList<HashMap>();
Document doc = StringSplitter.convertStringToDocument(result);
javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath();
NodeList node,node1;
try{
node =(NodeList)xPath.evaluate("/feed/entry/content/attrs/attr[#name='status_type']", doc, XPathConstants.NODESET);
node1 = (NodeList) xPath.evaluate("/feed/entry/content/attrs/attr[#name='count']", doc, XPathConstants.NODESET);
HashMap<String,String> hm = new HashMap<String,String>();
for(int i=0;i<node.getLength();i++)
{
hm.put(node.item(i).getTextContent(),node1.item(i).getTextContent() );
}
valuesFromRest.add(hm);
if(valuesFromRest.equals(valuesFromExcel))
{
AssertJUnit.assertTrue(true);
}
else
{
AssertJUnit.assertTrue(false);
}
}catch(Exception e) {
e.printStackTrace();
}
}
Expected XML Report
<logfile>
<logrecord>
<case>scenario</case>
<etime>Execution time</etime>
</logrecord>
</logfile>
Scenario is passed as a parameter in testcase
What you should instead do is to implement your own reporter: http://testng.org/doc/documentation-main.html#logging-reporters
public class TestManagerReporter implements IReporter {
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
// print <logfile>
for (ISuite suite : suites) {
for (IInvokedMethod method : suite.getAllInvokedMethods()) {
if (method.isTestMethod()) {
ITestResult result = method.getTestResult();
if (result.getStatus() == SUCCESS) {
// print <logrecord>
// print <case>
// print result.getName()
// print </case>
// print <etime>
// print result.getEndMillis() - result.getStartMillis()
// print </etime>
// print </logrecord>
}
}
}
}
// print </logfile>
}
}
I am building an android application that shows autocomplete feature and fetches autocomplete predictions in google maps using - GeoDataApi.getAutocompletePredictions. I followed this tutorial - https://github.com/googlesamples/android-play-places/blob/master/PlaceComplete/Application/src/main/java/com/example/google/playservices/placecomplete/PlaceAutocompleteAdapter.java
But somehow this is not working fine for me.
My class is this -
public class GooglePlacesAutoCompleteAdapter extends ArrayAdapter implements Filterable {
private ArrayList<PlaceAutocomplete> mResultList;
GoogleApiClient mGoogleApiClient;
private LatLngBounds mBounds;
private AutocompleteFilter mPlaceFilter;
int radius = 500;
public GooglePlacesAutoCompleteAdapter(Context context, int textViewResourceId, GoogleApiClient googleApiClient,
Location lastLocation, AutocompleteFilter filter) {
super(context, textViewResourceId);
LatLng currentLatLng = new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude());
mBounds = Utility.boundsWithCenterAndLatLngDistance(currentLatLng, 500, 500);
mGoogleApiClient = googleApiClient;
mPlaceFilter = filter;
}
#Override
public int getCount() {
return mResultList.size();
}
#Override
public PlaceAutocomplete getItem(int index) {
return mResultList.get(index);
}
#Override
public android.widget.Filter getFilter() {
Filter filter = new Filter() {
#Override
public FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null && constraint.length() > 3 && constraint.length()%3 == 1) {
// Retrieve the autocomplete results.
mResultList = autocomplete(constraint.toString());
// Assign the data to the FilterResults
filterResults.values = mResultList;
filterResults.count = mResultList.size();
}
return filterResults;
}
#Override
public void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
return filter;
}
public ArrayList<PlaceAutocomplete> autocomplete(String input) {
if (mGoogleApiClient.isConnected()) {
// Submit the query to the autocomplete API and retrieve a PendingResult that will
// contain the results when the query completes.
PendingResult results = Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, input.toString(),
mBounds, mPlaceFilter);
// This method should have been called off the main UI thread. Block and wait for at most 60s
// for a result from the API.
AutocompletePredictionBuffer autocompletePredictions = (AutocompletePredictionBuffer)results.await(60, TimeUnit.SECONDS);
// Confirm that the query completed successfully, otherwise return null
final Status status = autocompletePredictions.getStatus();
if (!status.isSuccess()) {
//Toast.makeText(getContext(), "Error contacting API: " + status.toString(),Toast.LENGTH_SHORT).show();
//Log.e(TAG, "Error getting autocomplete prediction API call: " + status.toString());
autocompletePredictions.release();
return null;
}
// Copy the results into our own data structure, because we can't hold onto the buffer.
// AutocompletePrediction objects encapsulate the API response (place ID and description).
Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
while (iterator.hasNext()) {
AutocompletePrediction prediction = iterator.next();
// Get the details of this prediction and copy it into a new PlaceAutocomplete object.
resultList.add(new PlaceAutocomplete(prediction.getPlaceId(), prediction.getDescription()));
}
// Release the buffer now that all data has been copied.
autocompletePredictions.release();
return resultList;
}
//Log.e(TAG, "Google API client is not connected for autocomplete query.");
return null;
}
class PlaceAutocomplete {
public CharSequence placeId;
public CharSequence description;
PlaceAutocomplete(CharSequence placeId, CharSequence description) {
this.placeId = placeId;
this.description = description;
}
#Override
public String toString() {
return description.toString();
}
}
}
The line on which GeoDataApi.getAutocompletePredictions is called, goes into an internal classes called - Filter.java, Log.java, handler.java and then Looper.java and loops there indefinetly on line 121 of Looper.java (I am sure studio sdk will show the code for Looper.java).
It is not even throwing an error, or going to the next line, it just does not work. Plus, I am not able to see the stack trace of an error.
This is the code snippet which is calling this -
if (mLastLocation != null) {
GooglePlacesAutoCompleteAdapter placesAdapter = new GooglePlacesAutoCompleteAdapter(this, R.layout.item_list, mGoogleApiClient, mLastLocation, null);
autoCompView.setAdapter(placesAdapter);
autoCompView.setOnItemClickListener(this);
}
Can someone please tell me what I am doing wrong here? Please any help will be greatly appreciated. I need to get this working as soon as I could.
PS - I am passing mPlaceFilter as null here.
Enable the Google Places API for Android in developers console
I am using Google cloud end point for my rest service. I am consuming this data in a GWT web client using RestyGWT.
I noticed that cloud end point is automatically enclosing a long datatype in double quotes which is causing an exception in RestyGWT when I try to convert JSON to POJO.
Here is my sample code.
#Api(name = "test")
public class EndpointAPI {
#ApiMethod(httpMethod = HttpMethod.GET, path = "test")
public Container test() {
Container container = new Container();
container.testLong = (long)3234345;
container.testDate = new Date();
container.testString = "sathya";
container.testDouble = 123.98;
container.testInt = 123;
return container;
}
public class Container {
public long testLong;
public Date testDate;
public String testString;
public double testDouble;
public int testInt;
}
}
This is what is returned as JSON by cloud end point. You can see that testLong is serialized as "3234345" rather than 3234345.
I have the following questions.
(1) How can I remove double quotes in long values ?
(2) How can I change the string format to "yyyy-MMM-dd hh:mm:ss" ?
Regards,
Sathya
What version of restyGWT are you using ? Did you try 1.4 snapshot ?
I think this is the code (1.4) responsible for parsing a long in restygwt, it might help you :
public static final AbstractJsonEncoderDecoder<Long> LONG = new AbstractJsonEncoderDecoder<Long>() {
public Long decode(JSONValue value) throws DecodingException {
if (value == null || value.isNull() != null) {
return null;
}
return (long) toDouble(value);
}
public JSONValue encode(Long value) throws EncodingException {
return (value == null) ? getNullType() : new JSONNumber(value);
}
};
static public double toDouble(JSONValue value) {
JSONNumber number = value.isNumber();
if (number == null) {
JSONString val = value.isString();
if (val != null){
try {
return Double.parseDouble(val.stringValue());
}
catch(NumberFormatException e){
// just through exception below
}
}
throw new DecodingException("Expected a json number, but was given: " + value);
}
return number.doubleValue();
}