Struts 1 custom validator - validation

I need to write custom validator which will simply check an array of strings for malformed data. This array of course comes from form as a property and actually it values comes from request through html:multibox tags (these are simple ID of elements in a string form). So I want to validate this data.
The problem is that official guide has nothing to say about handling non-string properties. I don't know how to retrieve this array.
Here is the example from struts valiator guide:
public static boolean validateTwoFields(
Object bean,
ValidatorAction va,
Field field,
ActionErrors errors,
HttpServletRequest request,
ServletContext application) {
String value = ValidatorUtils.getValueAsString(
bean,
field.getProperty());
String sProperty2 = field.getVarValue("secondProperty");
String value2 = ValidatorUtils.getValueAsString(
bean,
sProperty2);
if (!GenericValidator.isBlankOrNull(value)) {
try {
if (!value.equals(value2)) {
errors.add(field.getKey(),
Resources.getActionError(
application,
request,
va,
field));
return false;
}
} catch (Exception e) {
errors.add(field.getKey(),
Resources.getActionError(
application,
request,
va,
field));
return false;
}
}
return true;
}
As you can see this perfectly explains how to handle string values, but what about other types ?

I think, you should use PropertyUtils.getProperty() and then make use of the Object returned. You can see the example mentioned in the link below:
http://www.webkaifa.com/jsp/jakartaStrutsCookbook/059600771x/jakartastrutsckbk-chp-8-sect-9.html

Related

Call several different JavaScript within AjaxLink one after the other

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

Vibe.d basic form validation

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.

MVC 3 when is the Controller.ViewData.ModelState is populated

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.

ID in Spring-MVC 2.5 edit form using #Controller

I have a problem with the my Controller code. GET works fine (both empty form + form populated from db), POST works fine only for creating new object, but doesn't work for editing. Part of my #Controller class:
#RequestMapping(value = "/vehicle_save.html", method = RequestMethod.GET)
public String setUpForm(#RequestParam(value="id", required = false) Long id, ModelMap model) {
Vehicle v;
if (id == null) {
v = new Vehicle();
} else {
v = vehicleManager.findVehicle(id);
}
model.addAttribute("vehicle", v);
return "vehicle_save";
}
#RequestMapping(value = "/vehicle_save.html", method = RequestMethod.POST)
public String save(#ModelAttribute("vehicle") Vehicle vehicle, BindingResult result, SessionStatus status) {
vehicleValidator.validate(vehicle, result);
if (result.hasErrors()) {
return "vehicle_save";
}
if(vehicle.getId() == null) {
vehicleManager.createVehicle(vehicle);
} else {
vehicleManager.updateVehicle(vehicle);
}
status.setComplete();
return "redirect:vehicle_list.html";
}
The first method creates a vehicle object (including its ID). But the second method gets the same object without the ID field (set to null).
What could I do: manually set vehicle.setID(id from parameters) and then save it to database. This causes JPAOptimisticLockException + I don't like that solution.
Is there a way to pass my Vehicle object with ID to the second method? BTW, I would like to avoid adding hidden ID field to the JSP.
the example you suggested is using session to store the value. the #SessionAttribute is to bind an existing model object to the session. Look at the source code the class is annotated with #SessionAttributes("pet").Which means your model attribute named "pet" is getting stored in session.Also look at the code in processSubmit method of EditPetForm class
#RequestMapping(method = { RequestMethod.PUT, RequestMethod.POST })
public String processSubmit(#ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "pets/form";
}
else {
this.clinic.storePet(pet);
status.setComplete(); //look at its documentation
return "redirect:/owners/" + pet.getOwner().getId();
}
}
I havnt used something like this before.But i guess putting ur id in session is the way
BTW, I would like to avoid adding hidden ID field to the JSP.
This is common solution. What's wrong with it ? You should create hidden input with id.
May be you can try using session, cause you cant store info between two request. But that will be uglier i guess.
Btw, Can you please explain a little why you want to avoid adding hidden fields? I'm little curious

Checking to see if ViewBag has a property or not, to conditionally inject JavaScript

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.

Resources