type convert exception in spring mvc3 - spring

I am using sping3 mvc in my application.
I have some entities which need the CRUD operation.
When query the record,the pagination may be needed,so I create the class Pagination:
class Pagination{
int page,
int pageSize,
String sort;
}
This is my Dao:
public List<Post> list(Pagination pagination) {
/////
return xxx;
}
In controller:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String list(#RequestParam int page,#RequestParam int pageSize,#RequestParam String sort) {
List<Post> posts=postDao.list(new Pagination(page,pageSize,sort));
return "";
}
Now,if there no page or pageSize parameter in the httprequest,it will throw the typeconvert exception,in fact,I know I can redirect to the exception page but I do not want this. I want to use some default configuation in this case,for example:
http://xx/post/list ==>return all records without pagination
http://xx/post/list?page=1&pageSize=10&sort=id ==>pagination
http://xx/post/list?page=1 ==>pagination with the default pageSize(maybe 10) and sort(id)
http://xx/post/list?page=notnumber&pageSize=10 ==>pagination with page=1
Then I want to know where and how to validate and reset the Pagination parameter?

You can change your parameter datatype of int page and pageSize to String page and String pageSize, and after doing this you can just check whether the passed parameter values is not null. If parameter value is not null use passed value otherwise use default value.
like this
#RequestMapping(value = "/", method = RequestMethod.GET)
public String list(#RequestParam String page,#RequestParam String pageSize,#RequestParam String sort) {
if(page ==null)
page=1; // assign page default value 1 because user didn't pass page value.
if(pageSize==null)
pageSize=10; // assign pageSize default value 10 because user didn't pass pageSize value.
List posts=postDao.list(new Pagination(page,pageSize,sort));
return "";
}

You must understand that the parameters you send for request would be casted from String to int, for it better if you directly receive in String and call your constructor of Pagination.
You can use conditional instruction inline or other logic, up to u.
In this method u would call the constructor Pagination passing the values of request only when will be informed, another way will send default values that u must put in constants.
#RequestMapping(value = "/", method = RequestMethod.GET)
public String list(#RequestParam String page, #RequestParam String pageSize, #RequestParam String sort) {
List posts = postDao.list(new Pagination(
StringUtils.isEmpty(page) ? page : "1",
StringUtils.isEmpty(pageSize) ? pageSize : "15",
StringUtils.isEmpty(sort) ? sort : "asc"));
return "";
}

Related

How to get two attributes of a model in the same HTML file

Code
#RequestMapping(value = "/cars", params = "request")
public String showSomeAmountCars(HttpServletRequest request, Model model) {
String count = request.getParameter("count");
int parsedCount = Integer.parseInt(count);
model.addAttribute("someCars", carService.getCars(parsedCount));
return "cars";
}
In the method showSomeAmountCars I get some number of cars using parameter in URL link.
In the method showAllCars I get the whole list of cars.
Expected behavior
if I request /cars, then I get the list of cars from the HTML file
if I request /cars?count = 2, then I get the list of two cars from the same HTML file
Question
How can I get the two added attributes in the HTML file and make sure they don't conflict?
You can have an optional request parameter like this:
#GetMapping("/cars")
public String showSomeAmountCars(#RequestParam(name = "cars", required = false) Integer count, Model model) {
if( count == null ) {
model.addAttribute("cars", carService.getCars());
} else {
model.addAttribute("cars", carService.getCars(count));
}
return "cars";
}

Execute a simple call to a WebAPI Get using RestRequest and a single string parameter

I have the following code in my receiving controller:
[Route("api/StudentUserId/{string}"), HttpGet]
public StudentDto StudentUserId(string userId)
{
StudentModel sm = new StudentModel(userId);
StudentDto dto = sm.ConvertToDto();
return dto;
}
After running this project, I have another project that I use to test the WebAPI controller calls. I use the following code to read a student record form the database using their userId:
protected T SendRequestToReadItemUsingString<T>(string resource, string userId) where T : new()
{
string resourceString = string.Format("{0}/{{userId}}", resource);
RestRequest request = new RestRequest(resourceString, Method.GET);
request.AddUrlSegment("userId", userId);
RestClient restClient = new RestClient(Service.Location);
var response = restClient.Execute<T>(request);
T retVal = response.Data;
return retVal;
}
Comparible code seems to work if I change the userId to an int Id in both the controller and calling code. I can't seem to get it to work with string. If I place a breakpoint in the controller code it never hits it and the calling code just returns a null.
Thanks for your help
Please note that WebApi works based on reflection this means that your curly braces {vars} must match the same name in your methods.
Therefore to match this api/StudentUserId/{string} your method needs to be declare like this:
[Route("api/StudentUserId/{userId}"), HttpGet]
public StudentDto StudentUserId(string userId)
return userId;
}
Where the parameter {string} was replaced by userId.
If you want to read more about this Routing Rules here is similar post on this;
WebApi Routing Configuration

Regarding writing custom html helper for hidden field with few good feature ASP.Net MVC

this way i can write custom helper for hidden field
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Linq.Expressions;
namespace CustomHtmlHelpers.CustomHelpers
{
public static class CustomHiddenHelperModelBinding
{
//This overload accepts single expression as parameter.
public static MvcHtmlString Custom_HiddenFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
{
return Custom_HiddenFor(helper, expression, null);
}
//This overload accepts expression and htmlAttributes object as parameter.
public static MvcHtmlString Custom_HiddenFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes)
{
//Fetching the metadata related to expression. This includes name of the property, model value of the property as well.
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
//Fetching the property name.
string propertyName = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
//Creating a textarea tag using TagBuilder class.
TagBuilder hidden = new TagBuilder("input");
//Setting the type attribute to hidden to render hidden input field.
hidden.Attributes.Add("type", "hidden");
//Setting the name and id attribute.
hidden.Attributes.Add("name", propertyName);
hidden.Attributes.Add("id", propertyName);
//Setting the value attribute of textbox with model value if present.
if (metadata.Model != null)
{
hidden.Attributes.Add("value", metadata.Model.ToString());
}
//merging any htmlAttributes passed.
hidden.MergeAttributes(new RouteValueDictionary(htmlAttributes));
return MvcHtmlString.Create(hidden.ToString(TagRenderMode.Normal));
}
}
}
later we can access it like
#Html.Custom_HiddenFor(Model => Model.hidden)
#Html.Custom_HiddenFor(Model => Model.hidden, new { #class = "hiddenClass" })
my objective to rewrite my own html helper for hidden field is to render value at client side as encrypted text and as well as tamper proof.
if anyone tamper data then i want to check at server side and if tamper then i will show friendly error message to user.
this is another sampe code for encryption with machine key but i am not sure the that code works fine in partial trust environment or not?
here is the sample code
string Protect(byte[] data)
{
if (data == null || data.Length == 0) return null;
return MachineKey.Encode(data, MachineKeyProtection.All);
}
byte[] Unprotect(string value)
{
if (String.IsNullOrWhiteSpace(value)) return null;
return MachineKey.Decode(value, MachineKeyProtection.All);
}
here’s the 4.5 usage (it supports a slightly more sophisticated usage)
-------------------------------------------------------------------------
const string MachineKeyPurpose = "MyApp:Username:{0}";
const string Anonymous = "<anonymous>";
string GetMachineKeyPurpose(IPrincipal user)
{
return String.Format(MachineKeyPurpose,
user.Identity.IsAuthenticated ? user.Identity.Name : Anonymous);
}
string Protect(byte[] data)
{
if (data == null || data.Length == 0) return null;
var purpose = GetMachineKeyPurpose(Thread.CurrentPrincipal);
var value = MachineKey.Protect(data, purpose);
return Convert.ToBase64String(value);
}
byte[] Unprotect(string value)
{
if (String.IsNullOrWhiteSpace(value)) return null;
var purpose = GetMachineKeyPurpose(Thread.CurrentPrincipal);
var bytes = Convert.FromBase64String(value);
return MachineKey.Unprotect(bytes, purpose);
}
another way to encrypt
To generate a random string, use the RNGCryptoServiceProvider.
public string GenerateSalt(int length)
{
var rng = new RNGCryptoServiceProvider();
var buffer = new byte[length];
rng.GetBytes(buffer);
return Convert.ToBase64String(buffer);
}
Now we can generate a hashed password using the function below
public virtual string CreatePasswordHash(string password, string saltkey, string passwordFormat = "SHA1")
{
if (String.IsNullOrEmpty(passwordFormat))
passwordFormat = "SHA1";
string saltAndPassword = String.Concat(password, saltkey);
string hashedPassword =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltAndPassword, passwordFormat);
return hashedPassword;
}
so guide me how can i rewrite my own custom html helper which will encrypt data in most secure way and later which can be check to make sure the
value is tamper or not at client side.
i have another requirement to easily decrypt the value when form will post and action method will be called.
i want to decrypt the encrypted value using a attribute on action method. i want to fire a function will fire before action method and decrypt
value before data de-serialize to model or to action method argument.
is it possible ?
i want that my action method would look like
[HttpPost]
[Decrypt]
public ActionResult Save(string personname, string email)
{
return View();
}
or
[HttpPost]
[Decrypt]
public ActionResult Save(Person oPerson)
{
return View();
}
i want that my [Decrypt] attribute will fire a method call decypt and pass all value to decypt() function just before action method Save would invoke.
if decypt() function found any encrypted value then it will decrypt and de-serialize decypted value to model or to action method argument.
so i have three requirements
1) i want to write a custom html helper which will render hidden field with encrypted value.
2) when data post to server there i can detect that value has been tamper or not.
if tamper then a error page with proper message will be shown to user.
3)
action method will have custom attribute which will invoke a function before action method execution.
that function will decrypt value if any encrypted value found. after decryption the decrypted value will be properly De-serialize to model
or other action method argument properly.
i am new in MVC. so guide me how should i move forward with sample code. thanks
What about #Html.AntiForgeryToken()?
"Generates a hidden form field (anti-forgery token) that is validated when the form is submitted." Developer Network
Example:
1. In your markup add #Html.AntiForgeryToken() to the form.
2. Add [ValidateAntiForgeryToken] attribute your controller action.
Developer Network

REST with Spring Controller issue

I've my rest uri's as below
/leagues - Lists all the leagues organized so far
/leagues/{leagueName} - Details of the give leagueName
/leagues/{leagueName}/levels/ - Lists all the levels of a given league (For e.g. Playoffs, QF, SF etc)
Controllers
1.
#RequestMapping (value = "/leagues", method = RequestMethod.GET)
public String list(Model model)
{
return "/leagues/list";
}
2.
#RequestMapping (value = "/leagues/{leagueName}", method = RequestMethod.GET)
public String leagues(#PathVariable String leagueName, Model model)
{
return "/leagues/league";
}
3.
#RequestMapping (value = "/leagues/{leagueName}/levels", method = RequestMethod.GET)
public String levels(#PathVariable ("leagueName") String leagueName, Model model)
{
return "/leagues/levels/list";
}
The problem I am having is that the controller method for the (2) /leagues/{leagueName} is being invoked when I try (2) /leagues/levels/. Need help on how to fix this.
You forget to add the leguname to the url: use /leagues/SuperHero/levels/ instead (/leagues/levels/)
If you want to filter out /leagues/levels/`, then you can try to add an additional handler method:
#RequestMapping(value="/leagues/levels/")
for example, to return all levels of any league
The behavior is perfectly fine... The URL leagues/levels matches the second method's RequestMapping...
If you want to invoke the third method u need the URL as leagues/[some string]/levels

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

Resources