Show status code description depending on the current status code - c#

I have an application that is going to be used to change the status code of production units to track them throughout the process. My current issue is displaying the status code description depending on the status code of the currently selected record. I have a method that I think will do the job, but I do not know where to put it to perform the desired actions. I have a 2NF Microsoft Access (.mdb) database on the backend that has all of the desired information and is built properly, but I am having trouble working with it through C#.
public void DescLabel()
{
if (statusCodeLabel.Text == "-5")
{
statusCodeDescLabel.Text = "Problem with Unit.";
}
if (statusCodeLabel.Text == "10")
{
statusCodeDescLabel.Text = "Manufacturing Order Created.";
}
if (statusCodeLabel.Text == "15")
{
statusCodeDescLabel.Text = "Stock Room in Process.";
}
if (statusCodeLabel.Text == "20")
{
statusCodeDescLabel.Text = "Picked by Stock Room.";
}
}

You could simply add a property to your Production Unit model class, called StatusDescription and have it return the strings above based on its internal status code. Then, just call that property from your UI to get the text you desire.
public StatusDescription {
get {
if (statusCode == 15) {
return "Stock Room in Process.";
}
// etc, etc.
return string.Empty;
}
}
Then just...
statusCodeLabel.Text = productionUnit.StatusDescription;
And update your UI when it is required to be updated. Either on a change of state. Or on a timer, whatever your application requires.
That said, it's something that sounds like it should be in the database already and mapped to your model class via the status code in question.

Related

Impossible result after executing a custom MS CRM 8.2 workflow action

The following is a fragment of a custom MS CRM workflow activity:
[Input("Input name")]
public InArgument<string> InputName { get; set; }
private string InputNameValue
{
get
{
return InputName.Get(Context);
}
}
[Output("Success")]
public OutArgument<bool> Success { get; set; }
[Output("Result Message Details")]
public OutArgument<string> ResultMessageDetails { get; set; }
[Output("Integer result")]
public OutArgument<int> ResultInt { get; set; }
private CodeActivityContext Context { get; set; }
(...)
try
{
ResultInt.Set(Context, -1);
var query = new QueryByAttribute("my_customentity") { ColumnSet = new ColumnSet("my_customentityid") };
if (!String.IsNullOrEmpty(InputNameValue))
query.AddAttributeValue("my_name", InputNameValue);
OutputId.Set(Context, null);
var results = service.RetrieveMultiple(query).Entities;
if (results.Count == 1)
{
OutputId.Set(Context, results.Single().ToEntityReference());
Success.Set(Context, true);
ResultInt.Set(Context, 1);
ResultMessageDetails.Set(Context, "");
}
else
{
ResultInt.Set(Context, 2);
Success.Set(Context, false);
ResultMessageDetails.Set(Context, "Could not find the specified entity by name.");
}
}
catch (Exception ex)
{
ResultInt.Set(Context, 3);
Success.Set(Context, false);
ResultMessageDetails.Set(Context, ex.Message);
}
Note that the code sets up ResultInt to -1 in the first line. No matter what happens afterwards, this output property should always be set to 1, 2 or 3. I've confirmed that output workflow parameters can be set multiple times and overwritten as needed. Also note that an OutArgument<int> will, by default, be 0.
However, every once in a while a workflow will fail, and the logs will show that ResultInt was... -1, and the expected OutputId parameter is null. This is an impossible case also for another strange reason - the queried custom entity record DOES exist in the system. It is as if this code is terminated mid-execution without any warnings. Do note that subsequent workflow steps are being executed as if nothing wrong had happened, with the incorrect outputs as described above. If there was an exception inside the catch clause, then that should have been propagated "upwards" and logged in CRM, preventing execution of subsequent workflow steps. When I write that the "workflow will fail" I mean that the empty result from this custom activity is later processed by another step, which cannot use a blank value.
Unfortunately, I'm out of ideas on how to potentially debug this issue. Worse yet, is that this is a very freakish occurrence that cannot be replicated. If this ever occurs then a simple "retry" will yield a correct result.
I could enable maximum tracing on the affected CRM server and hope I manage to get something that would indicate what the issue is, but I was hoping someone else might have seen something similar already. My best guess so far is that something odd happens when the query gets executed by CRM (service.RetrieveMultiple call) and for some reason the system flips out and terminates the activity, but I have no idea why that would happen.

How to get the latest ID from Firebase console from Untiy

I have a Unity project with Firebase for google Authentication. I am storing user information in a realtime database. They are stored as:
UnityProject
1->
Name: "Something"
Email: "Something"
2->
Name: "some other thing"
Email: "Something else"
Now, these 1,2 are to be given by me (to be used as a primary key). I would start by giving the first user ID 1 and the second used ID 2 and so on.
But I need to get back from the firebase the last ID which was stored. For example,
idToInsert = GetLastUsedID() + 1;
I have used this code but it doesn't work. The screen just freezes until I force close Unity.
public int GetLastUsedID()
{
int currentID = 1;
bool continueSearch = true;
while (continueSearch)
{
FirebaseREST.DatabaseReference reference = FirebaseREST.FirebaseDatabase.Instance.GetReference(""+currentID);
string value = "";
currentID++;
reference.GetValueAsync(10, (res) =>
{
if (res.success)
{
value = res.data.GetRawJsonValue();
Debug.Log("Success fetched data : " + value);
if(value == "")
{
continueSearch = false;
Debug.Log(currentID);
}
}
else
{
Debug.Log("Fetch data failed : " + res.message);
continueSearch = false;
}
});
}
return currentID;
}
Basically I am just trying to iterate from 1 till whenever I get the empty string. The empty string means no data exists under that ID.
I'm not familiar with FirebaseREST (I would recommend using the official Firebase plugin if you're able, it does much more than just call REST endpoints), but I think I can see your issue.
GetValueAsync likely runs asynchronously in the background. So the logic inside the block (the (res)=> part) is firing off many times (basically infinitely with that while loop). Then, depending on how this is implemented, either continueSearch never goes to false because it isn't marked volatile or the callback logic never gets a chance to run (say if FirebaseREST tries to dispatch to the main thread, which is locked in an infinite while loop).
If GetValueAsync returns a Task, you can use some of the tips I cover in this article. My recommendation would be to try to use async/await, so your logic would look more like:
async public int GetLastUsedID()
{
volatile int currentID = 1;
volatile bool continueSearch = true;
while (continueSearch)
{
FirebaseREST.DatabaseReference reference = FirebaseREST.FirebaseDatabase.Instance.GetReference(""+currentID);
string value = "";
currentID++;
await reference.GetValueAsync(10, (res) =>
{
if (res.success)
{
value = res.data.GetRawJsonValue();
Debug.Log("Success fetched data : " + value);
if(value == "")
{
continueSearch = false;
Debug.Log(currentID);
}
}
else
{
Debug.Log("Fetch data failed : " + res.message);
continueSearch = false;
}
});
}
return currentID;
}
This is probably not the case, in which case you'll probably want to turn this into a recursive call. You'd want some function like:
public void GetLastUsedID(currentId)
{
FirebaseREST.DatabaseReference reference = FirebaseREST.FirebaseDatabase.Instance.GetReference(""+currentID);
reference.GetValueAsync(10, (res) =>
{
if (res.success)
{
value = res.data.GetRawJsonValue();
Debug.Log("Success fetched data : " + value);
if(value == "")
{
continueSearch = false;
Debug.Log(currentID);
}
else
{
// recurse
GetLastID(currentId+1);
}
}
else
{
Debug.Log("Fetch data failed : " + res.message);
continueSearch = false;
}
});
}
You will have to figure out how to pass in your own callback to bubble a success or failure like this (exercise to the reader).
Finally, I would be a little cautious with what you're doing entirely. If you're authenticating users, I'd recommend using Firebase Authentication which ties directly into Realtime Database. At most you'd only store user id's in there, and use security rules to ensure that only that user can write into it (for instance). By using Firebase Authentication to manage user data and tying that to RTDB rules, you avoid the same mistakes this author made.

Security/Validation on c# property change N-Tier

I have a class that keeps track of Property Changes
public class Property
{
object _OriginalValue;
object _ProposedValue;
DateTime _ProposedDateTime;
List<Property> _History = new List<Property>();
public object OriginalValue
{
get
{
return _OriginalValue;
}
set
{
_OriginalValue = value;
}
}
public object ProposedValue
{
get
{
return _ProposedValue;
}
set
{
_ProposedDateTime = DateTime.Now;
_ProposedValue = value;
}
}
public bool IsDirty
{
get
{
if (OriginalValue != ProposedValue)
{
return true;
}
else
{
return false;
}
}
}
}
This property can be used by classes like
public class Customer
{
protected Property _FirstName = new Property();
public string FirstName
{
get
{
return (string)_FirstName.ProposedValue;
}
set
{
_FirstName.ProposedValue = value;
}
}
public object GetOriginalValue(Property Property)
{
return Property.OriginalValue;
}
}
The question is, is there a way to secure the original value when passing this to a client in an N-Tier architecture?
When a client passes a Customer back into the Service Boundary - by default you can't trust the client. You need to either reload the original values from the database or validate that the original values are untampered. Of course I'm assuming we're going to use business logic based on the current values in the customer to reject or allow an update operation.
Example:
User inserts record with Name Bob.
User fetches record with Name Bob and changes name to Ted. Original Value is Bob, proposed Value is Ted.
User sends Customer to Service to Update Customer.
Everything is good.
*A business rule is now coded into the service that says if the customer's name is Ted - allow the update else throw "unable to update" exception. *
User fetches record with name Ted.
User changes name to Darren.
User changes name back to Ted - system throws exception.
User fetches Ted. User cheats and uses a tool to change the OriginalPropertyValue on the client.
The server doesn't refetch the OriginalValue from the database and simply reads the OriginalValue coming from the client.
User bypasses business rule.
Actually there're more issues with your approach than just checking if original value hasn't been tampered. For example, I suspect that's a multi-user environment where more than an user would be able to edit the same object. That is, the original value mightn't be tampered, but changed before other has already saved a new original value in the database.
I guess you're already applying some kind of optimistic or pessimistic locking on your data...
About your actual concern, probably you need to sign your original value, and whenever you're going to store those objects back in the database, your application layer should check that original value hasn't been tampered (from Wikipedia):
Digital signatures are a standard element of most cryptographic
protocol suites, and are commonly used for software distribution,
financial transactions, contract management software, and in other
cases where it is important to detect forgery or tampering.

Exception handling design from class libarary

I'm looking for some program design guidance.
I have a class library that handles data in a database. I have a winforms app that is the presentation layer for the user to input and manage data. Say for example the user inputs some data and attempts to save it. From the winforms app I do something like:
MyTool theTool = new MyTool();
MyTool.FirstName = this.Textbox1.Text;
MyTool.LastName = this.Textbox2.Text;
//etc...
int result = MyTool.SaveData(); //result is the ID of the inserted record.
MyTool is a type in my class library. Within this type I would have:
public int SaveData()
{
if (IsReadyForInput())
{
//..open a DB connection and save out the data
//..get the ID of the saved record
}
else
{
throw new ArgumentException("One or more arguments prevented saving the data");
}
return theID
}
private bool IsReadyForInput()
{
if (this.FirstName.Length == 0)
{ return false; }
if (this.LastName.Length == 0)
{return false;}
return true;
}
Now, what I'm interested in is the best design on how exception handling should work. For example the above method is not specific at all so the user doesn't know what's wrong. So I could rewrite this to do something like:
public void SaveData()
{
string errMess = IsReadyForInput();
if (errMess.Length == 0)
{
//..open a DB connection and save out the data
//..get the ID of the saved record
}
else {
throw new ArgumentException(errMess);
}
return theID
}
private string IsReadyForInput()
{
if (this.FirstName.Length == 0)
{ return "Specify a first name"; }
if (this.LastName.Length == 0)
{return "Specify a last name";}
return true;
}
However it just doesn't seem a very elegant (or fast) method to be comparing string lengths to find an error message. I had tried writing something like:
public void SaveData()
{
ValidateInput();
//..open a DB connection and save out the data
return theID
}
private void ValidateInput()
{
if (this.FirstName.Length == 0)
{ throw new ArgumentException("Specify a first name"; }
if (this.LastName.Length == 0)
{throw new ArgumentException("Specify a first name"; }
}
The problem with this is that the exception is actually thrown by ValidateInput when the front end is calling "SaveData", so when the exception reaches the top, to me, it would seem less clear (especially if there are multiple ways of calling "ValidateInput()" from within MyTool).
Additionally I am not sure what the best way to handle the exception on the front end would be because, if an error is thrown, the ID is never returned.
I guess I am just looking for some guidance on how to handle this situation and validation/error handling in general. Thanks for any help.
The first thing I wonder about is whether you need to throw an exception at all when ordinary control flow might be enough:
if (IsReadyForInput())
{
//..open a DB connection and save out the data
//..get the ID of the saved record
}
else
{
//..do whatever you need in case of invalid input
}
The obvious problem with this suggestion is that we are in a method somewhere in your class library, and some of the desired effects (displaying warnings to the user, etc.) happen in the WinForms layer. That, however, suggests a better solution; namely, to do the validation in the WinForms code:
if (IsReadyForInput())
{
int result = theTool.SaveData();
//...and whatever else should happen.
}
else
{
//..do whatever you need in case of invalid input
}
The above approach is simpler and makes the parts of your program less dependent on each other (as MyTool doesn't need to care about validation of user input) when compared to, e.g., throwing an exception or using special return values to signal failure.
Take a look at FluentValidation (http://fluentvalidation.codeplex.com/). I think it's what you're looking for.
With it you can define your validation rules and call its validation methods. It will return a full list of potential validation errors without causing exceptions to be thrown in your code.

When to Throw an Exception? When to Handle an Exception (Service Layer, Controller) where?

I rewritten my question as I think it was too wordy and maybe what I am trying to achieve was lost.
I written this code in notepad so it may have mistakes and some stuff maybe not well thoughout but it is to illustrate what I see my options are.
// I wrap all code send back from service layer to controller in this class.
public class ResponseResult
{
public ResponseResult()
{
Errors = new Dictionary<string, string>();
Status = new ResponseBase();
}
public void AddError(string key, string errorMessage)
{
if (!Errors.ContainsKey(key))
{
Errors.Add(key, errorMessage);
}
}
public bool IsValid()
{
if (Errors.Count > 0)
{
return false;
}
return true;
}
public Dictionary<string, string> Errors { get; private set; }
public ResponseBase Status { get; set; }
}
public class ResponseResult<T> : ResponseResult
{
public T Response { get; set; }
}
public class ResponseBase
{
public HttpStatusCode Code { get; set; }
public string Message { get; set; }
}
Option 1 (what I am using now)
//controller
public HttpResponseMessage GetVenue(int venueId)
{
if (venueId == 0)
{
ModelState.AddModelError("badVenueId", "venue id must be greater than 0");
if (ModelState.IsValid)
{
var venue = venueService.FindVenue(venueId);
return Request.CreateResponse<ResponseResult<Venue>>(venue.Status.Code, venue);
}
// a wrapper that I made to extract the model state and try to make all my request have same layout.
var responseResult = new ResponseResultWrapper();
responseResult.Status.Code = HttpStatusCode.BadRequest;
responseResult.Status.Message = GenericErrors.InvalidRequest;
responseResult.ModelStateToResponseResult(ModelState);
return Request.CreateResponse<ResponseResult>(responseResult.Status.Code, responseResult);
}
// service layer
public ResponseResult<Venue> FindVenue(int venueId)
{
ResponseResult<Venue> responseResult = new ResponseResult<Venue>();
try
{
// I know this check was done in the controller but pretend this is some more advanced business logic validation.
if(venueId == 0)
{
// this is like Model State Error in MVC and mostly likely would with some sort of field.
responseResult.Errors.Add("badVenueId", "venue id must be greater than 0");
responseResult.Status.Code = HttpStatusCode.BadRequest;
}
var venue = context.Venues.Where(x => x.Id == venueId).FirstOrDefault();
if(venue == null)
{
var foundVenue = thirdPartyService.GetVenue(venueId);
if(foundVenue == null)
{
responseResult.Status.Code = HttpStatusCode.NotFound;
responseResult.Status.Message = "Oops could not find Venue";
return responseResult;
}
else
{
var city = cityService.FindCity(foundVenue.CityName);
if(city == null)
{
city = cityService.CreateCity(foundVenue.CityName);
if(city.Response == null)
{
responseResult.Status.Code = city.Status.Code;
responseResult.Status.Message = city.Status.Message;
return responseResult;
}
CreateVenue(VenueId, city.Response, foundVenue.Name);
responseResult.Status.Code = HttpStatusCode.Ok;
// I don't think I would return a success message here as the venue being displayed back to the user should be good enough.
responseResult.Status.Message = "";
reponseResult.Response = foundVenue;
}
}
return responseResult;
}
}
catch (SqlException ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
// maybe roll back statement here depending on the method and what it is doing.
}
// should I catch this, I know it should be if you handle it but you don't want nasty messages going back to the user.
catch (InvalidOperationException ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
}
// should I catch this, I know it should be if you handle it but you don't want nasty messages going back to the user.
catch (Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
}
return responseResult;
}
// another service layer.
// it is ResponseResult<City> and not city because I could have a controller method that directly calls this method.
// but I also have a case where my other method in another service needs this as well.
public ResponseResult<City> CreateCity(string CityName)
{
ResponseResult<City> responseResult = new ResponseResult<City>();
try
{
City newCity = new City { Name = "N" };
context.Cities.Add(newCity);
context.SaveChanges();
responseResult.Status.Code = HttpStatusCode.Ok;
responseResult.Status.Message = "City was succesfully added";
}
// same catch statmens like above
catch (SqlException ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
// maybe roll back statement here depending on the method and what it is doing.
}
return responseResult;
}
As you can see the methods are all wrapped in the status codes as they could be directly called by the controller being public. FindCity() and CreateVenue() could also have this wrapping.
Option 2
public HttpResponseMessage GetVenue(int venueId)
{
try
{
if (venueId == 0)
{
ModelState.AddModelError("badVenueId", "venue id must be greater than 0");
if (ModelState.IsValid)
{
var venue = venueService.FindVenue(venueId);
return Request.CreateResponse<ResponseResult<Venue>>(HttpSatusCode.Ok, venue);
}
// a wrapper that I made to extract the model state and try to make all my request have same layout.
var responseResult = new ResponseResultWrapper();
responseResult.Status.Code = HttpStatusCode.BadRequest;
responseResult.Status.Message = GenericErrors.InvalidRequest;
responseResult.ModelStateToResponseResult(ModelState);
return Request.CreateResponse<ResponseResult>(responseResult.Status.Code, responseResult);
}
catchcatch (SqlException ex)
{
// can't remember how write this and too tried to look up.
return Request.CreateResponse(HttpStatusCode.InternalServerError;, "something here");
}
}
public Venue FindVenue(int venueId)
{
try
{
// how to pass back business logic error now without my wrapper?
if(venueId == 0)
{
// what here?
}
var venue = context.Venues.Where(x => x.Id == venueId).FirstOrDefault();
if(venue == null)
{
var foundVenue = thirdPartyService.GetVenue(venueId);
if(foundVenue == null)
{
// what here?
}
else
{
var city = cityService.FindCity(foundVenue.CityName);
if(city == null)
{
city = cityService.CreateCity(foundVenue.CityName);
if(city == null)
{
// what here?
}
CreateVenue(VenueId, city.Response, foundVenue.Name);
}
}
return venue;
}
}
catch (SqlException ex)
{
// should there be a try catch here now?
// I am guessing I am going to need to have this here if I need to do a rollback and can't do it in the controller
// throw exception here. Maybe this won't exist if no rollback is needed.
}
return null;
}
public City CreateCity(string CityName)
{
// if it crashes something I guess will catch it. Don't think I need to rollback here as only one statement being sent to database.
City newCity = new City { Name = "N" };
context.Cities.Add(newCity);
context.SaveChanges();
return newCity;
}
As you see with option 2, I might still need to wrap it in try catches for rollbacks and I am not sure how to handle advanced business validation.
Also with catching everything in the controller and sending back vanilla objects(without my wrapper) I am unsure how to do fine grain HttpStatus codes(say like notFound,Create and such)
Sorry for the brief response, but here is my general rule - if an exception occurs which you expect might happen, deal with it - either by retrying or telling the user something went wrong and giving them options to fix it.
If an unexpected exception occurs, if it's something you can deal with (e.g a timeout which you can retry) try to deal with it, otherwise get out - just think what any MS app does - e.g. office - you get an apology that something went wrong and the app ends. It's better to end gracefully than to potentially corrupt data and leave things in a real mess.
This is an article with Java-specific concepts and examples, but the broad principles here are the way to go.
Distinguish between fault exceptions, which are catastrophic and unrecoverable, and contingency exceptions, which are very much recoverable. Let the faults "bubble" to the fault barrier, where you handle appropriately. For example, you might log the error, E-mail someone or send a message to a message queue, and present the user with a nice, informative error page.
Whatever you do, be sure to preserve all the exception information from the source.
Hope that helps.
Throw an exception wherever your code determines that something has gone wrong.
You always need to handle exceptions in methods which are called directly by the end-user. This is to cater for unexpected errors which your code doesn't have specific handling for. Your generic handling code would typically log the error and may or may not include letting the user know that an unexpected error has occurred.
But if there are errors which you can expect ahead of time, you'll often want to handle these lower down in the code, nearer to the point at which they occur, so that your application can "recover" from the error and continue.
I think exceptions are useful any time you need to return details of a failure from a method, whilst being able to use the ideal return type for the method you're calling.
You said in your question:
Now for me I try to return error messages back to the the controller
and try not to really catch anything in the controller.
If the service method is supposed to ideally return a Venue object, how do you return this potential error message back to the controller? an out parameter? change the return type to something which has an error message property on it?
If you're doing either of those options, I think you're reinventing the wheel... i.e. creating a way to return exception information when one already exists.
Finally, Exceptions are strongly typed representations of what went wrong. If you return an error message, then that is fine to send back to the user, but if you need to programatically do different things based on the details of the error, then you don't want to be switching on magic string.
For example, wouldn't it be handy to differentiate between authorization errors and not found errors so you can return the most appropriate http status code to the user?
Don't forget that the Exception class has a Message property you can simply return to the user if you want to use it that way
To make sure I understand the question, your are creating a web service and want to know when to handle and when to throw exceptions.
In this situation I would strongly recommend that you catch all exceptions. "Unhandled" exceptions are very bad form. On web sites they result in displays that range from meaningless to dangerous by exposing internal information that you do no want the public to see.
If this is a good sized program I suggest that you create your own MyException class which derives from System.Exception. The purpose of this is provide a place for you to add additional information specific to your application. Here are some typical things I like to add to my MyException classes:
An ID number that will help me find the location in the code where the problem occurred.
A "LogMessage" method that logs the exception, sometimes to the Windows Event Log. Whether or not you log and to which log you write depends on what you want recorded, and the severity of the situation.
An indicator that shows the exception has been logged so the above method will not log twice even if it gets called more than once.
Anything else that might be useful given the circumstance.
I also like to put the text of the messages in an external resource file, like an XML document, and key them to the error number that you assign. This allows you to change the error text to improve clarity without having to redeploy the application.
Catch all exceptions and create a new instance of your MyException type and put the original exception into inner exception property. Below the first level of my application, I always throw one of my MyException instances rather than the original exception.
At the top level (application level), NEVER let an exception go unhandled and never throw your own exception. A better way is to return an error code and message in your data contract. That way the client application will only get what you want them to see. The only exceptions they'll need to worry about are the ones outside your scope, i.e. configuration errors or communication failures. In other words if they are able to invoke your service and the network stays connected you should give them a response they can interpret.
Hope this helps.
PS I didn't include a sample exception as I am sure a little searching will find many. Post if you want me to put up a simple sample.
Use try catch at all levels and bubble it up. Optionally, log the error in a file or database. I use text file - tab delimited. Capture at each level
1. Module Name (Use C# supplied methods to get this)
2. Method Name
3. Code Being Executed (User created - "Connecting to database")
4. Error Number
5. Error Description
6. Code Being Executed (User created - "Accessing database")
7. Error Number for the end user
8. Error Description for the end user
Additionally, I also pass a unique identifier like - Session Id in case of Web, Logged in User Id, User Name (if available)
I always have the Exception catch block. In here I set the error number as -0 and the message from the exception object as the error description. If it is SQL Server related - I capture SQL Exception. This generates an error number - I use that.
I want to extend this some more though.

Categories

Resources