I have a post create method:
void gönderiyiOluştur(HTTPServerRequest istek, HTTPServerResponse yanıt)
{
render!("gönderiler/oluştur.dt")(yanıt);
}
and a post store method like this:
void gönderiyiKaydet(HTTPServerRequest istek, HTTPServerResponse yanıt)
{
auto başlık = istek.form["baslik"];
auto içerik = istek.form["icerik"];
bool yayınla = false;
if (başlık.length > 0)
{
Gönderi gönderi = Gönderi(başlık, içerik);
gönderi.kaydet();
yanıt.redirect("/");
}
else
{
yanıt.redirect("/gönderiler/oluştur");
}
}
I'd like to make basic form validation. For example if input fields are empty it redirects to previous page.
I suppose I should pass some error message to the create method like baslik field should not be empty etc..
But since I am quite new to framework I shouldn't figure out. Are there any facilities does the framework offer for form validation.
Basic form validation is easy when you use the web framework from vibe.d. The basic steps are:
Create a class Gönderiyi and put your kaydet method inside this class:
class Shipment {
#method(HTTPMethod.POST)
void kaydet() { ... }
}
Define a method inside the class which should be called in case a validations fails. This method should display the error message:
void getError(string _error = null, HTTPServerResponse res) { ... }
Annotate the kaydet method with the #errorDisplay attribute to connect the method with the error function:
class Shipment {
#method(HTTPMethod.POST)
#errorDisplay!getError
void kaydet() { ... }
void getError(string _error = null, HTTPServerResponse res) { ... }
}
Now do the validation inside the kaydet method and throw an exception in case of an error. The getError method is then called automatically. You can take advantage of parameter binding and conversion, too. When the D parameter name is the same as the name of an HTML input value, then this value is bind to the D parameter. Automatic type conversion takes place (e.g. to int) and can lead to exceptions, which are then handled in the getError method, too.
As last step you need to register your class with the web framework:
auto router = new URLRouter;
router.registerWebInterface(new Gönderiyi);
You should have a look at the documentation of errorDisplay and at the web framework example from vibe.d, too.
Related
When I click on an AjaxLink, I would like to have a validation via JavaScript on the client side first (because the LocalStorage is queried) and then depending on the result, further JavaScript calls are made. How can i achieve this?
In a pseudo code it would look like this:
new AjaxLink<>("myId", myModel) {
#Override
public void onClick(AjaxRequestTarget target) {
boolean isCounterValid = target.appendJavaScript(checkCounter()); // i know that this is not possible, therefore pseudo code
if(isCounterValid) {
target.appendJavaScript(someOtherJavaScript());
}
else {
target.appendJavaScript(anotherJavaScript());
}
}
private String checkCounter() {
return "var count = window.localStorage.getItem('myCounter'); return count !== 1;";
}
private String someOtherJavaScript() {
return "change something";
}
private String anotherJavaScript() {
return "change other thing";
}
};
You need to send extra request parameters with the Ajax call when the link is clicked. For that you should override updateAjaxAttributes(AjaxRequestAttributes attributes) method of AjaxLink:
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
{
attributes.getDynamicExtraParameters().add("var count = window.localStorage.getItem('myCounter'); return [{\"name\":\"count\", \"value\": count}]");
}
This way inside AjaxLink#onClick() you can read the count via:
int count = getRequest().getRequestParameters().getParameterValue("count").toInt();
AJAX components and behaviors can customize AJAX attributes overriding updateAjaxAttributes and using a custom implementation of AjaxCallListener which exposes different method to hook into the AJAX request cycle. In you case you could use AjaxCallListener#getBeforeSendHandler.
For a full introduction to this topic (with examples) see user guide:
https://ci.apache.org/projects/wicket/guide/8.x/single.html#_ajax_request_attributes_and_call_listeners
I have this call on one view model
ShowViewModel<MyViewModel>(
new MyParams { ... }
);
On MyViewModel I have this Init method which works perfect
public void Init(MyParams params)
{
if (params != null)
{
// some logic
}
else
{
// some other logic
}
}
On another view model I have
ShowViewModel<MyViewModel>();
I expect to receive null on MyViewModel init method, instead of that I get an instance of 'MyParams'. That's generating problems since I have specific logic to handle the call with no parameters
I have custom presenter logic that might responsible for this, but at first sight I couldn't identify any custom logic as responsible. Is this the standard behavior for complex params?
Unfortunately, no there isn't a way to pass null using a parameters object.
The reason is that when Mvx creates the ViewModel and attempts to call the Init method, it will first convert your object instance into a simple dictionary (key/value pairs). If you use the no arg version, then it creates an empty dictionary. At this point, it creates an MvxBundle which includes the dictionary.
When Mvx is finally ready to call your Init method, it takes this dictionary and attempts to create an actual object.
It's this method that creates the instance to pass to Init.
MvxSimplePropertyDictionaryExtensionMethods.Read()
https://github.com/MvvmCross/MvvmCross/blob/8a824c797747f74716fc64c2fd0e8765c29b16ab/MvvmCross/Core/Core/Platform/MvxSimplePropertyDictionaryExtensionMethods.cs#L54-L72
public static object Read(this IDictionary<string, string> data, Type type)
{
var t = Activator.CreateInstance(type);
var propertyList =
type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy).Where(p => p.CanWrite);
foreach (var propertyInfo in propertyList)
{
string textValue;
if (!data.TryGetValue(propertyInfo.Name, out textValue))
continue;
var typedValue = MvxSingletonCache.Instance.Parser.ReadValue(textValue, propertyInfo.PropertyType,
propertyInfo.Name);
propertyInfo.SetValue(t, typedValue, new object[0]);
}
return t;
}
Notice how it calls Activator.CreateInstance(type) which will always return an instance.
So that is why you'll never get an null value in Init.
My recommendation is to simply add a property to your MyParams object and set that in your no-arg version. Then in Init you can check the property to determine what to do.
Something like:
ShowViewModel<MyViewModel>(new MyParams { HasNoParams = true });
public void Init(MyParams myParams)
{
if (myParams.HasNoParams)
{
// do null flow here
}
else
{
// do non-null flow here
}
}
You can use Dictionary< TKey, TValue> as your params.
Currently I am reading the MVC 3 source code to try to find when is the Controller's ModelState is set.
From the code I can see from Controller.cs that ModelState property was delegated to its ViewData's ModelStata property, like the code below:
public ModelStateDictionary ModelState {
get {
return ViewData.ModelState;
}
}
However I can only see the ViewData.ModelState seems only populated through ValidateModel() method in Controller.cs, like the code below:
protected internal void ValidateModel(object model, string prefix) {
if (!TryValidateModel(model, prefix)) {
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentCulture,
MvcResources.Controller_Validate_ValidationFailed,
model.GetType().FullName
)
);
}
}
in above code TryValidateModel() method would indirectly populate the Controller.ModelState like code below:
foreach (ModelValidationResult validationResult in ModelValidator.GetModelValidator(metadata, ControllerContext).Validate(null)) {
ModelState.AddModelError(DefaultModelBinder.CreateSubPropertyName(prefix, validationResult.MemberName), validationResult.Message);
}
However I searched through all the source code and did not find any place that calls ValidateModel() method, and also from the access modifier, this method is protected, I wonder how this method is called by MVC 3 framework during the request processing, or ValidateModel() is only supposed to be called by user in the inherited controller class.
Consider this simple controller:
Porduct product = new Product(){
// Creating a product object;
};
try
{
productManager.SaveProduct(product);
return RedirectToAction("List");
}
catch (Exception ex)
{
ViewBag.ErrorMessage = ex.Message;
return View("Create", product);
}
Now, in my Create view, I want to check ViewBag object, to see if it has Error property or not. If it has the error property, I need to inject some JavaScript into the page, to show the error message to my user.
I created an extension method to check this:
public static bool Has (this object obj, string propertyName)
{
Type type = obj.GetType();
return type.GetProperty(propertyName) != null;
}
Then, in the Create view, I wrote this line of code:
#if (ViewBag.Has("Error"))
{
// Injecting JavaScript here
}
However, I get this error:
Cannot perform runtime binding on a null reference
Any idea?
#if (ViewBag.Error!=null)
{
// Injecting JavaScript here
}
Your code doesnt work because ViewBag is a dynamic object not a 'real' type.
the following code should work:
public static bool Has (this object obj, string propertyName)
{
var dynamic = obj as DynamicObject;
if(dynamic == null) return false;
return dynamic.GetDynamicMemberNames().Contains(propertyName);
}
Instead of using the ViewBag, use ViewData so you can check for the of the item you are storing. The ViewData object is used as Dictionary of objects that you can reference by key, it is not a dynamic as the ViewBag.
// Set the [ViewData][1] in the controller
ViewData["hideSearchForm"] = true;
// Use the condition in the view
if(Convert.ToBoolean(ViewData["hideSearchForm"])
hideSearchForm();
I would avoid ViewBag here completely.
See my thoughts here on this:
http://completedevelopment.blogspot.com/2011/12/stop-using-viewbag-in-most-places.html
The alternative would be to throw a custom error and catch it. how do you know if the database is down, or if its a business logic save error? in the example above you just catch a single exception, generally there is a better way to catch each exception type, and then a general exception handler for the truly unhandled exceptions such as the built in custom error pages or using ELMAH.
So above, I would instead
ModelState.AddModelError()
You can then look at these errors (assuming you arent jsut going to use the built in validation) via
How do I access the ModelState from within my View (aspx page)?
So please carefully consider displaying a message when you catch 'any' exception.
You can use ViewData.ContainsKey("yourkey").
In controller:
ViewBag.IsExist = true;
In view:
if(ViewData.ContainsKey("IsExist")) {...}
I need to test this but:
#if (ViewBag.ABoolParam ?? false)
{
//do stuff
}
I think will give you either the value of the ViewBag property, or return a default value if missing.
I'm trying to write a generic method parameter validation functionality that can be chained (fluent interface) to attach more and more validations/checks like:
public void SomeMethod(User user, string description)
{
ParameterHelper
.Create(() => user)
.RejectNull();
ParameterHelper
.Create(() => description)
.RejectNull()
.RejectEmptyString();
// now this would be luxurious
ParameterHelper
.Create(() => new { user = user, desc = description })
.RejectNull(o => o.user)
.RejectNull(o => o.desc)
.RejectEmptyString(o => o.desc);
}
I would like to use this helper class to test method parameters for certain values before using them (most of the time null will be tested).
Current state of affairs
I first started writing static helper class without the Create() method like:
public static class ParameterHelper
{
public static void RejectNull(Expression<Func<T>> expr)
{
if (expr.Compile()().Equals(default(T)))
{
MemberExpression param = (MemberExpression)expr.Body;
throw new ArgumentNullException(param.Member.Name);
}
}
}
But this doesn't allow chaining. That's why I created the Create() method that would return something that can be used by chained extension methods.
The problem
I would like to avoid multiple Compile() calls, so basically my Create() method should return Func<T> and reject methods should be extension methods of Func<T>.
If my Create() does return Func<T> I don't get the chance to read parameter names that should be supplied to various exceptions (using MemberExpression).
If I return Expression<Func<T>> instead I will have to call Compile() in each Reject extension method.
Questions
Is there a C# library that already does this kind of chaining?
If not, what do you suggest how this should be done? Any examples from the web would be warmly welcome.
Additional note
I should point out that complex/long validation invocation code is not an option here, because my current validation is done like:
if (user == null)
{
throw new ArgumentNullException("user");
}
or
if (string.IsNullOrEmpty(description))
{
throw new ArgumentNullException("description");
}
Which has two major drawbacks:
I repeat the same lines of code over and over
it uses magic strings
So validation should be done with a one liner per check as described above in the desired scenario.
There is a simple way to implement such a fluent interface. Your 'ParameterHelper.Create' method should return an instance of some class (this class is named Requirements below). This instance should hold the expression which was passed to Create. Also this class should have Require... instance methods which will validate expression and return this. Requirements class can be a private class inside ParameterHelper. I would also introduce an interface for this requirements chain (this interface is named IRequirements below. Sample:
public static class ParameterHelper
{
public static IRequirements Create<T>(Expression<Func<T>> expression)
{
return new Requirements{ Expression = expression };
}
private class Requirements<T> : IRequirements
{
public readonly Expression<Func<T>> Expression { get; set; }
public IRequirements RejectNull()
{
if (Expression .Compile()().Equals(default(T)))
{
MemberExpression param = (MemberExpression)Expression.Body;
throw new ArgumentNullException(param.Member.Name);
}
return this;
}
// other Require... methods implemented in the same way
}
}
public interface IRequirements
{
IRequirements RejectNull();
}
This approach will allow you implementing your luxurious solution - you just need to add a corresponding parameters to Reject... methods. Also you will probably need to make IRequirements interface generic.
Robert,
I have a library that solves this problem. It is called Bytes2you.Validation (Project). It is fast, extensible, intuitive and easy-to-use C# library providing fluent APIs for argument validation.
It focuses exactly on the problem that you want to solve, but does not use expressions. This is so, because they are a lot slower than just passing the argument name. For a library like that, that is designed to be used everywhere the performance is one of the most critical features.
For example:
Guard.WhenArgument(stringArgument,"stringArgument").IsNullOrEmpty().IsEqual("xxx").Throw();
// Which means - when stringArgument is null or empty OR is equal to "xxx" we will throw exception. If it is null, we will throw ArgumentNullException. If it is equal to "xxx", we will throw ArgumentException.