UPDATE - Due to lack of explanation from my side, I've rewritten the post.
What do you think about using Code Contracts to throw exceptions on invalid input?
(I'm coding against a contract for my Service which requires the UserName not to be null or contain whitespaces)
MembershipServiceContracts.cs - Located in the service layer in a subfolder
[ContractClassFor(typeof (IMemberShipService))]
internal abstract class MemberShipServiceContracts : IMemberShipService
{
#region IMemberShipService Members
public MembershipCreateStatus CreateUser(string userName, string password, string email)
{
Contract.Requires(!String.IsNullOrWhiteSpace(userName), "Test");
Contract.Requires(!String.IsNullOrWhiteSpace(password));
Contract.Requires(!String.IsNullOrWhiteSpace(email));
return default(MembershipCreateStatus);
}
#endregion
}
MembershipService.cs - Located in my service layer
[ContractClass(typeof (MemberShipServiceContracts))]
public interface IMemberShipService
{
MembershipCreateStatus CreateUser(string userName, string password, string email);
}
public class MemberShipService : IMemberShipService
{
private readonly MembershipProvider _provider;
public MemberShipService()
: this(null)
{ }
public MemberShipService(MembershipProvider provider)
{
_provider = provider ?? Membership.Provider;
}
#region IMemberShipService Members
public MembershipCreateStatus CreateUser(string userName, string password, string email)
{
MembershipCreateStatus status;
_provider.CreateUser(userName, password, email, null, null, true, null, out status);
return status;
}
#endregion
}
AccountController.cs - located at the UI layer
Now this is the interesting part...
Should I use:
[Authorize(Roles = "Developer")]
[HttpPost]
public ActionResult Create(CreateUserViewModel model)
{
if (!String.IsNullOrEmpty(model.UserName))
{
throw new ArgumentException("UserName May not be null or contain only white spaces.", model.UserName);
}
if (!String.IsNullOrEmpty(model.Password))
{
throw new ArgumentException("Password May not be null or contain only white spaces", model.Password);
}
if (!String.IsNullOrEmpty(model.Email))
{
throw new ArgumentException("Email May not be null or contain only white spaces", model.Email);
}
if (!ModelState.IsValid)
{
return Json("Model validation failed");
}
MembershipCreateStatus newUser = _memberShipService.CreateUser(model.UserName, model.Password,
model.Email);
return Json(newUser != MembershipCreateStatus.Success ? "Failed" : "Success");
}
or:
[Authorize(Roles = "Developer")]
[HttpPost]
public ActionResult Create(CreateUserViewModel model)
{
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(model.UserName),
"UserName May not be null or contain only white spaces.");
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(model.Password),
"Password May not be null or contain only white spaces");
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(model.Email),
"Email May not be null or contain only white spaces");
if (!ModelState.IsValid)
{
return Json("Model validation failed");
}
MembershipCreateStatus newUser = _memberShipService.CreateUser(model.UserName, model.Password,
model.Email);
return Json(newUser != MembershipCreateStatus.Success ? "Failed" : "Success");
}
to throw the an exception if the code contracts for the CreateUser() method isnt fulfilled?
Thanks in advance.
A failure in a Code Contract indicates that your code has a serious bug that should be fixed. It doesn't replace validation of user input. Rather, you would first validate your user input, then attempt to process the data if determined to be valid (otherwise prompt the user to re-enter). If you then don't satisfy the target contract with your valid data, then an uncatchable exception will be thrown as you pretty obviously have a bug.
I hoped it would be a silver bullet but quickly realised I still needed my validation. After that, I grew to really love the way code contracts will replace all of my usual guard code.
Think of all the times you would get a NullReferenceException (too many for me!). Code Contracts can take that pain all away.
R.
P.s. Also, don't use contracts to validate security-sensitive data as code contracts can be turned off at runtime...
I'm afraid to say: it depends on how you want to use code contracts.
You'd better look at the user manual, section "Usage Guidelines". Here's a small excerpt:
The easiest use of the contract tools
is if you decide that you don't need
to perform argument validation at
runtime in release builds (Usage 1).
In that case, you use the contract
tools during development, but not on
the shipped bits. Remember, you can
ship a contract reference assembly
along with your release bits so 18
clients can get runtime checking of
your parameter validations on their
debug builds via call-site requires
checking. The second easiest approach
if you need argument validation in
your release build is to turn on
contract checking in all builds (Usage
2). You therefore take advantage of
the tools to produce the runtime
strings of your conditions and to
perform contract inheritance for you.
You can choose to produce specic
exceptions for your parameter
validations, or have the default
ContractException.
I'd suggest you read the whole section before making any big decisions.
Both of the approaches are fine .
The 3 ways that one has for checking pre conditions are
Contract.Requires -> a particular condition must be true upon entry to the method.
Contract.Requires -> Same as above but throw exception if condition not met
Requires is always compiled, so use of this method entails a hard dependency on the tools. You should decide if you want that before using this method.
Your first approach --> The benefit of this type of precondition is that it is always there to perform the runtime check.
In the first approach you might want to add Contract.EndContractBlock();
I am exploring this feature myself but I think you can throw exception in your service layer and it is ok.
HTH
Related
I've got a class User which has an attribute Name that must be unique.
So far I've investigated 3 ways of checking this:
Annotations
[StringLength(100)]
[Index(IsUnique = true)]
public string Name { get; set; }
Problem is, by trying to insert a user with a repeated name it throws this ex:
as you can see, I would have to navigate into the inner exceptions (which I don´t know if it is possible, but I assume it is) and the last inner exception´s message is not user friendly at all.
Fluent Api
https://stackoverflow.com/a/23155759/5750078
I haven´t tried it but I believe it is has the same problem that Annotations.
Check by hand
controller code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Name,Password,Profile")] User user)
{
if (ModelState.IsValid)
{
lock (locker)
{
validateNameUnicity();
db.Users.Add(user);
db.SaveChanges();
}
return RedirectToAction("Index");
}
return View(user);
}
Problem: the check depends on my code, which may not be as accurate as date base checkings. Besides I will need to program more logic than the other two options. And last but no least if somehow I access the database directly there will be no checks at all.
I need to know which is the best practice to do this, because I'm trying to learn on my own, and I would like to do things as best as possible.
You should actually do both, a check in code and a uniqueness index as a final guard when concurrent users manage to insert identical records after all. (Because of the latency between the check and the actual insert).
This means that you always have to catch exceptions when you call SaveChanges, but that's not a bad idea anyway.
For the uniqueness check you could use the mechanism I described here, just change email into Name and you're good to go.
You could dig up the last exception message from a chain of inner exceptions by this extension method:
public static string GetDeepestExceptionMessage(this Exception exception)
{
string msg = string.Empty;
while (exception != null)
{
msg = exception.Message;
exception = exception.InnerException;
}
return msg;
}
Here is my code:
public class UserPreferences
{
/// <summary>
/// The EMail signature.
/// </summary>
[UserPreferenceProperty(Category = "Email", DefaultValue = "My default value")]
public static string Signature
{
get
{
return UserPreferenceManager.GetValue();
}
set
{
UserPreferenceManager.SetValue(value);
}
}
}
public static string GetValue()
{
if (((VTXPrincipal)Thread.CurrentPrincipal).VTXIdentity.OperatorID == null)
{
throw new Exception("Missing Operator ID");
}
string value = string.Empty;
var frame = new StackFrame(1); ***** <------ problem here.....
var property = frame.GetMethod();
var propertyname = property.Name.Split('_')[1];
var type = property.DeclaringType; ***** <------ problem here.....
if (type != null)
{
var userPreference = typeof(UserPreferences).GetProperty(propertyname).GetCustomAttributes(true).FirstOrDefault() as UserPreferencePropertyAttribute;
if (userPreference != null)
{
string category = userPreference.Category;
string description = propertyname;
value = GetValue(category, description, ((VTXPrincipal)Thread.CurrentPrincipal).VTXIdentity.OperatorID);
if (value == null)
{
// always return something
return userPreference.DefaultValue;
}
}
else
{
throw new Exception("Missing User Preference");
}
}
return value;
}
Inside the GetValue method, StackFrame works differently in release mode vs. debug mode.
In debug mode, I correctly get the property name as signature
But in Release mode, property name is GetUserPreferenceValueTest because this is the test method that makes the calls as clients.
There fore my code works in debug mode but fails in release mode.
Q. How can I use StackFrame properly so it works in Debug vs. Release modes.
Q. Is there any other way to get calling property name and related information at run time?
I answered a similar question once, please read my answer here.
In short, this is a very bad design decision because your method is a hypocrite—it talks different to different callers but doesn't tell it in open. Your API should never, ever rely on who calls it. Also, the compiler can break the stack trace in an unexpected way due to language features like lambdas, yield and await, so even if this worked in Release mode, it would certainly break some day.
You're effectively building a complex indirection mechanism instead of using language feature designed for passing information to methods—method parameters.
Why do you use attributes? Do you read them elsewhere?
If you do, and you don't want to repeat "Email" both as parameter to GetValue call and attribute value, you may consider passing a property Expression<> to GetValue, which will extract the attribute. This is similar to your solution, but it is explicit:
[UserPreferenceProperty(Category = "Email", DefaultValue = "My default value")]
public string Signature
{
get { return GetValue (prefs => prefs.Signature); }
set { SetValue (prefs => prefs.Signature, value); }
}
This answer shows how to implement this.
I see you are checking Thread.CurrentPrincipal in your code. Again, this is not a really good practice because it is not obvious to client code that accessing a property can result in an exception. This is going to be a debugging nightmare for someone who supports your code (and trust me, your code may run for years in production, long after you move onto another project).
Instead, you should make VTXIdentity a parameter to your settings class constructor. This will ensure the calling code knows you enforce security on this level and by definition knows where to obtain this token. Also, this allows you to throw an exception as soon as you know something is wrong, rather than when accessing some property. This will help maintainers catch errors earlier—much like compile errors are better than runtime errors.
Finally, while this is a fun exercise, there are plenty performant and tested solutions for storing and reading configuration in C#. Why do you think you need to reinvent the wheel?
Assuming your problem survives the discussion of whether you could just use another library rather than rolling your own... if you find yourself using C# 5 &.NET 4.5, take a look at the CallerMemberName attribute. With CallerMemberName you can modify your GetValue() method signature to be
public static string GetValue([CallerMemberName] string callerName = "")
The property can then call GetValue() with no parameter and you'll get the property name passed into GetValue() as you want.
I'm a IT student, second year. We just learned to program with 3 layers, one for getting data with a class, one for manipulating stuff with requests (all of the methods go in here) and one for the working of the program itself. Seeing as the first two go into classes instead of a form I dont know how to show errors.
Example:
We need to make a login system with a webbrowser and some other stuff behind it. So I make the login in a class, but how to check back for errors? I don't think it's normal or even possible to do MessageBox.Show(error); from a class, I can only return stuff, but I want the username/id to be returned if possible.
So in short, what is the best/most accepted way to report errors that are caused by data, so from a class?
Your framework level API's (eg. your layers) should use Exceptions for real errors, and return values to report non-critical errors.
public class Login
{
public bool AccountExists(string name) {
bool exists;
// do checking
return exists;
}
public LoginResult Login(string name, string password) {
// Try login
// If successful
return LoginResult.Success;
// What if the user does not exist?
return LoginResult.AccountNotFound;
// What about an error?
return LoginResult.Error;
}
}
public enum LoginResult
{
None,
AccountNotFound,
Error,
Success
}
In the example above, you can report the status of operations through return values. For LoginResult this could even be a value type (struct) that contains more information about the result (eg. a string message or something). Because these types of operations on non-critical, there is no necessity for exceptions here. Exceptions are costly and not always necessary to report errors.
Now let's talk about a different type of error. Logical developer errors. These should be handled by throwing exceptions. Take this example (assume we have some type Account that has a Role property).
public class Foo
{
public bool IsAdmin(Account account) {
if (account == null) {
throw new System.ArgumentNullException("You cannot pass a null account!");
}
return account.Role == "Admin";
}
}
We know as a developer that the account should not be null, so we should check for it and throw an exception if it is. If this exception is ever thrown, its a bug in the calling code and should be fixed not to pass in a null value.
Now that I've given two rough scenarios, how does this apply to your question? These are API's. Whatever your UI layer is, whether it be a WinForm, WPF Window, WebForm, or some other UI, the UI only has to use the API. The API is responsible for reporting information that can be usable by the UI, and the UI is responsible for displaying info in whatever way is best suited for that UI.
The framework API layers should never be responsible for reporting an error to the user with a UI. They should only be responsible for reporting errors to the developer who can take the result, and wire it up to the UI layer in some fashion. You would never display a message box or write to a console from a framework API for example. You would return some result that the UI can use to display its own message.
I highly recommend that you read Framework Design Guidelines. It covers a lot of this material and is an extremely great read.
You should have a class which validates the data object and returns error information. Then your front-end code can ask this class to validate the data and show any error messages that get returned.
var username = GetUserName();
var password = GetPassword();
var validationResult = new Validator().ValidateLogin(username, password);
if(validationResult.ErrorMessage != null) {
MessageBox.Show(validationResult.ErrorMessage);
} else {
// Do what you would have done.
}
If any errors occur that are outside of the expected logic flow, they should throw an exception.
Well you can use Exceptions. You Just throw the exception, it is up to the caller on what to do with the exception.
class Login
{
public Login()
{
}
public bool CheckLogin(string userName, string password)
{
// Do your validation here.
If every thing goes fine
return True.
else
throw Exception("custom message.");
}
}
class Input //class which takes input.
{
Login login = new Login();
public void TakeInput(string username, string password)
{
try
{
login.CheckLogin(username, password);
}
catch(Exception ex)
{
MessageBox.show(ex.message);
}
}
}
I have been trying to develop an app using the repository pattern like in the Nerd Dinner application however I would like to handle exceptions in the repository and pass the exception messages back to the controller so that I can output the message in a nice page to the user.
How do I pass back this exception message, or even pass that an exception has occured in the repository.
http://www.asp.net/ajaxlibrary/jquery_errors.ashx
In the following example from the above url, "_repository.HasErrors" is used as a check but I want to know what the implementaion of this is in the repository in C# as I dont know how this is implemented and also if its possible to also get the error message as well.
01.// GET: /HandlejQueryErrors/Contact/Create
02.public ActionResult Create()
03.{
04. return View();
05.}
06.
07.// POST: /HandlejQueryErrors/Contact/Create
08.[HttpPost]
09.public ActionResult Create(ContactViewModel viewModel)
10.{
11. var response = new AjaxResponseViewModel();
12.
13. try
14. {
15. var contact = _repository.SaveOrUpdate(viewModel);
16. if (!_repository.HasErrors)
17. {
18. response.Success = true;
19. response.Message = "Your contact was successfully created!";
20. }
21. else
22. {
23. response.Message = "There was an error updating your contact!";
24. }
25. }
26. catch (Exception exception)
27. {
28. response.Success = false;
29. response.Messages exception.Message;
30. }
31.
32. return Json(response);
33.}
Thanks in advance.
You could allow your repository's exceptions to fall through, and override your controller's OnActionExecuted method to handle specific errors for you. Example:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception is RepositoryException)
{
filterContext.ExceptionHandled = true;
filterContext.Result = View("Exception", filterContext.Exception);
}
base.OnActionExecuted(filterContext);
}
So, in general in ASP.NET MVC you need to handle 2 kinds of errors: Validation errors, and System errors.
For System errors, those occurring because of some system rules violation (like foreign key constraint violation in database during insert), you should use try-catche operator and then pass them to the view in some way to show them to the user.
For validation errors, you should read about ASP.NET MVC Validation:
Validation with the Data Annotation Validators - here you can see how to validate simple validation rules using built-in annotation attributes.
Validating with a Service Layer - this is more advanced topic, where you can learn how to validate more complex validation rules (for example for inter-connected properties, etc.)
So, as a conclusion, think of separating the concerns about domain/business functionality from the concerns related to validation. The only common thing they should have (in the perfect scenario) is a view where you show the results of validation.
Personally I (taking 2-nd approach) even do a save in validation, so that Validation implementation knows about domain/business logic and manipulates it to validate all the rules. In the end of validation, if all rules were met, then it tries to save the data, and returns the validation error message in case of non-success. This is also a good start to go further and even localize your custom validation messages.
I hope this helps!
I personally still like the GetRuleViolations() approach started by ScottGu and would simply follow this through on the Repository.
In the controller I would do (pseudo here):
[HttpPost]
public ActionResult ControllerAction(MyViewModel viewModel)
{
ModelState.AddRuleViolations(viewModel.GetRuleViolations);
if (!ModelState.IsValid)
{
return View();
}
// Perform repository action (pseudo code to follow)
_repository.ClearErrorState();
_repository.DoSomething();
ModelState.AddRuleViolation(repository.GetRuleViolations());
if (!ModelState.IsValid)
{
return View();
}
return RedirectToAction("Foo","Bar");
}
class Repository
{
List<RuleViolation> _errors = new List<RuleViolation>();
public void ClearErrorState()
{
_errors.Clear();
}
public void DoSomething(...)
{
try
{
DoSomthingThatFails();
}
catch (Exception ex)
{
_errors.Add(new RuleViolation(null, "Error while saving customer");
_errors.Add(new RuleViolation("SSN", "SSN must be unique"); // This one I struggle with as bad design, tying UI element to data elements is bad, so generally I try to prevent everything when checking the viewmodel and only catch general (unforeseen) errors here.
}
}
public IEnumerable<RuleViolation> GetRuleViolations()
{
return _errors;
}
}
In many cases in web applications you would need to return an error message, rather than simple true/false result. One would use exceptions for that, but I consider exceptions to be an indication of, you know, exceptional behavior. Let's take a Register() function for a class User for instance. If it was successful we can simply return true, but if something went wrong we would like to know what exactly: "passwords don't match", "e-mail is in invalid format" and so on (could be an error code instead of a message, doesn't matter).
The question is what is the best practice for returning such error messages in C# and .Net? There might be a struct ready, something like:
public struct Result {
public bool OK;
public string Message;
}
Or perhaps I should just use a parameter in the function? Like Register(out string Message).
Update. This pretty much describes everything I need: http://blogs.msdn.com/kcwalina/archive/2005/03/16/396787.aspx
If it's for validation purposes I would recommend you the excellent Fluent Validation library.
Quote from the site:
using FluentValidation;
public class CustomerValidator: AbstractValidator<Customer> {
public CustomerValidator() {
RuleFor(customer => customer.Surname).NotEmpty();
RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
RuleFor(customer => customer.Company).NotNull();
RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
RuleFor(customer => customer.Address).Length(20, 250);
RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
}
private bool BeAValidPostcode(string postcode) {
// custom postcode validating logic goes here
}
}
Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
bool validationSucceeded = results.IsValid;
IList<ValidationFailure> failures = results.Errors;
I think exceptions can and should be used here.
You can put your Register() call in a try/catch block therefore preventing application execution stop. In the catch block you will analyze what exactly got wrong and return an appropriate message.
I think exception should be used when it comes to program mistakes and IO communication.
This means:
non-validated input
a bug in the software. (adding 2 equal keys to dictionaries)
disk access/network/cross application/ etc
For a Register method i should either use a boolean for result checking.
if(Register("someone", "password"))
{
// success
}
else
{
// failed
}
or if you like more details on the result, specify a result enum:
public enum RegisterResult
{
Success,
BadUsernamePassword,
PasswordTooShort
}
RegisterResult result = Register("someone", "password");
switch(result)
{
case(RegisterResult.Success):
// success
break;
case(RegisterResult.BadUsernamePassword):
// failed
break;
case(RegisterResult.PasswordTooShort):
// failed
break;
}
If you need more information like a userId, you should define it as a output parameter
int userId = 0;
RegisterResult result = Register("someone", "password", out userId);
etc...
So if an exception is thrown, this means 1 of 3 things.
Some of the input (by user) is not validated. ' (negligence of the programmer)
There is bug in it. (like accessing disposed objects or something serious. etc.)
There is an IO problem. (connecting lost from database.. etc)
I advice u to use exceptions only in exceptional situations. A bad login isn't an exception, it's a user fault.
Regards,
Jeroen
Throwing exceptions creates CPU utilization while adding all call stack and setting other fields of exception class.
I prefer not to throw Exceptions. If it is really casual error like say Argument is null,i would go for struct with an ExceptionMessage field with it.
But it is better to type-value check before calling a method and expecting primitive types to return from the method since you need a boolean value return to.