I am trying to use html entities in in a DropDownList control. The reason I am using entities is because I want to display units with superscripts such as m²/s or kg/m³. sup is not an option because it doesn't work inside a select option tag. I have created a small example that illustrates my problem. Here is my aspx page:
<!DOCTYPE html>
<html lang="en">
<head runat="server">
<meta charset="utf-8" />
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<select>
<option value="1">M³/min</option>
<option value="2">M³/s</option>
</select>
<asp:DropDownList ID="drp" runat="server"></asp:DropDownList>
</div>
</form>
</body>
</html>
and here is my code behind:
public partial class MyPage: System.Web.UI.Page
{
private class idAndUnit
{
public int Id { get; set; }
public string Unit { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
var units = new List<idAndUnit>()
{
new idAndUnit
{
Id = 1,
Unit = "M³/min"
},
new idAndUnit
{
Id = 2,
Unit = "M³/min"
}
};
drp.DataSource = units;
drp.DataTextField = "Unit";
drp.DataValueField = "Id";
drp.DataBind();
}
}
If you run the page and look at the source html it generates you see the following:
<select>
<option value="1">M³/min</option>
<option value="2">M³/s</option>
</select>
<select name="drp" id="drp">
<option value="1">M³/min</option>
<option value="2">M³/min</option>
As you can see the DropDownList version has changed M³/min into M³/min.I'm not sure why this change happens presumably either to be helpful in some way or perhaps a security reason for preventing xss or something like that. Is it possible to prevent this behaviour here so I can get the output I'm after?
Just figured it out
using HttpUtility.HtmlDecode("M³/min") fixes it.
Related
Hi I'm having some trouble retrieving information from the user using a spring controller.
the controller looks like this:
#Slf4j
#Controller("indexController")
public class IndexController {
List<String> userInput = new ArrayList<>(Arrays.asList(new String[]{"Apple", "Blackberry", "Strawberry"}));
public List<String> getUserInput() {
return userInput;
}
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String home(
Model model
){
log.info("home path was hit");
model.addAttribute("options", getUserInput());
model.addAttribute("option", new Object());
return "index";
}
#RequestMapping(value = "createOrder", method = RequestMethod.POST)
public String placeUserOrder(
Model model,
#ModelAttribute("option")String usersInput
){
log.info("createOrder path was hit");
log.info(usersInput);
return "redirect:/home";
}
the index.thml within re main/resource/templates folder looks like this:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>home page</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h2>your orders are:</h2>
<form method="post" action="/createOrder" th:object="${order}">
<th:text alignment-baseline="text-before-edge" aria-atomic="true" > select a copybook</th:text>
<select class="from-control" id="dropDownList">
<option value="0">select copybook</option>
<option th:each="option : ${options}" th:value="${option}" th:text="${option}" >
<input type="hidden" name="${_csrf.usersChoiceFromThymeleaf}" value="${_csrf.token}" />
</option>
<input type="submit" name="createOrder" value="place">
</select>
</p>
</p>
</form>
<th:block th:each="order : ${orders}">
<tr>
<td th:text="${order.value}"></td>
</tr>
</th:block>
</body>
</html>
every time after i set a breakpoint within the post function the option value is empty.
what am i doing wrong?
shouldnt i expect a string from selected dropdown menu?
i tried to fetch an int and it remains empty as well
the model contains also only 2 key value pairs "option"->""
and org.springframework.validation.BindingResult.option -> {BeanPropertyBindingResult#7472} "org.springframework.validation.BeanPropertyBindingResult: 0 errors"
I've the following domain:
#Document(collection = "backupareas")
public class BackupArea {
#Id
private String id;
private String area;
private List<Tape> tapes;
In my template I would that when I change area a js function fill the tape select with related area tapes.
<div class="form-group col-md-3">
<label for="backup"><i>*</i> Backup</label>
<select id="backup" class="form-control" name="backup" required onchange="loadTapes();">
<option value="" selected="selected">--- Select Area ---</option>
<option th:each="area: ${areas}" th:value="${area.getArea()}" th:text="${area.getArea()}"></option>
</select>
</div>
<div class="form-group col-md-3">
<label for="tape"><i>*</i> Tape</label>
<select id="tape" class="form-control" name="tape" required >
</select>
I start with this js function, but I don't know how to use (or if it is possible) model variables.
function loadTapes() {
var area = $("#backup").val();
console.log($("#backup").index(area));
if($("#backup").index(area) == 1) {
$("#tape").empty();
return false;
}
$("#tape").empty();
var select = $('#tape');
select.append($("<option />").val("").text("--- Select one ---"));
// Here should use model variable to loop over tapes related to the selected area
select.append($("<option/>").val(TAPE).text(TAPE));
}
I solved. I created a fragment as:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<th:block th:fragment="tapes">
<th:block th:if="${tapes != null}">
<option th:each="tape: ${tapes}" th:value="${tape}" th:text="${tape}"></option>
</th:block>
</th:block>
</body>
</html>
In the main template I call an ajax method:
function loadTapes() {
$("#tape").empty();
$.post("/area/loadTapes", {area: area}, function (data) {
$('#tape').append(data);
});
}
The loadTapes method is:
PostMapping("/area/loadTapes")
public String loadTape(#RequestParam("area") String area, Model model) {
BackupArea backupArea = backupAreaService.findByArea(area);
List<Integer> tapes = new ArrayList<>();
for(Tape tape: backupArea.getTapes()) {
tapes.add(tape.getTape());
}
model.addAttribute("list", tapes);
return "/backup/tapes :: list";
}
addMission.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Create a mission</title>
</head>
<body>
<h1>Create a Mission</h1>
<form action="/createMission" method="post">
<p>Mission title: <input type="text" required id="title" name="title" value=""></p>
<p>
<select name="agent" id="agent">
<option value="natasha">Natasha Romanova</option>
<option value="austin">Austin Powers</option>
<option value="johnny">Johnny English</option>
</select>
</p>
<h2>Enter the gadgets</h2>
<p>Gadget 1:<input type="text" required id="gadget1" name="gadget1" value=""></p>
<p>Gadget 2:<input type="text" required id="gadget2" name="gadget2" value=""></p>
<p><input type="submit" value="Create Mission!"></p>
</form>
<p> Back to home </p>
</body>
</html>
Controller Code
#PostMapping("/createMission")
public String createMission(#ModelAttribute Mission mission) {
int returnValue = database.createMission(mission);
System.out.println(returnValue);
return "view_missions";
}
createMission() method
public int createMission(Mission mission) {
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
String query = "INSERT INTO missions(agent, title, gadget1, gadget2) VALUES (:agent, :title, :gadget1, :gadget2)";
namedParameters
.addValue("agent", mission.getAgent())
.addValue("title", mission.getTitle())
.addValue("gadget1", mission.getGadget1())
.addValue("gadget2", mission.getGadget2());
int returnValue = jdbc.update(query, namedParameters);
return returnValue;
}
In the code snippets shared above, Im creating a mission using thymleaf.
When I enter the details in the textboxes and hit "Create" button I get an error 'Property or field 'empty' cannot be found on null'. Im sure this null property is coming from the dropdown list.
Is there any way I can get the value of the dropdown too along with the other values and send them to the createMission() ?
I don't see in your controller how you get back the values.
You need to add an object to your model in your "get controller" and link it to the form.
Then you can retrieve it and save it in the database.
Please have a look to this post you will get more details on how to make it
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Super Spy App</title>
</head>
<body>
<h1>Our Super Cool Spy App</h1>
<h2>Create a Mission</h2>
<form action="/addMission" method="post">
<p><input type="submit" value="Create a Mission"></p>
</form>
<form action="/viewMission" method="get">
<h2>View Missions for</h2>
<select id="agents" name="agents">
<option value="Johnny English">Johnny English</option>
<option value="Natasha Romanova">Natasha Romanova</option>
<option value="Austin Powers">Austin Powers</option>
</select>
<input type="submit" value="Go">
</form>
</body>
</html>
ViewMissions.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>View Missions</title>
</head>
<body>
<h1> Here are the missions for</h1>
<div th:if="${missionList.empty}">
<h2>No Current Missions</h2>
</div>
<div th:unless="${missionList.empty}">
<table border="1">
<tr>
<th>Title</th>
<th>Gadget 1</th>
<th>Gadget 2</th>
<th colspan="2">Operation</th>
</tr>
<tr th:each="mission : ${missionList}">
<td th:text="${mission.title}"></td>
<td th:text="${mission.gadget1}"></td>
<td th:text="${mission.gadget2}"></td>
<td>edit</td>
<td>delete</td>
</tr>
</table>
</div>
<p> Back to home </p>
</body>
</html>
Controller Class
#GetMapping("/")
public String Home() {
return "index";
}
#PostMapping("/addMission")
public String addMission(Model model) {
model.addAttribute("mission", new Mission());
return "create_mission";
}
#GetMapping("/createMission")
public String ViewMission1(Model model) {
List<Mission> mission1 = database.getMissions();
model.addAttribute("missionList", mission1);
return "view_missions";
}
#PostMapping("/createMission")
public String createMission(#ModelAttribute Mission mission) {
int returnValue = database.createMission(mission);
System.out.println(returnValue);
return "view_missions";
}
#GetMapping("/viewMission")
public String viewMission2(Model model) {
List<Mission> mission1 = database.getMissions();
model.addAttribute("missionList", mission1);
return "view_missions";
}
getMissions method
public List<Mission> getMissions() {
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
String query = "SELECT * FROM missions";
BeanPropertyRowMapper<Mission> missionMapper = new BeanPropertyRowMapper<Mission>(Mission.class);
List<Mission> missions = jdbc.query(query, namedParameters, missionMapper);
return missions;
}
Mission.java (the getter setter are already set but I didn't paste them here to prevent hustle and bustle)
public class Mission {
private Long id;
private String agent;
private String title;
private String gadget1;
private String gadget2;
}
So, in the above examples, I want to send the value selected from the dropdown list to my controller.
Im my html, if I select any value from the dropdown and press 'Go' it shows me the whole database for all the 3 agents but not the particular one that I selected.
Any suggestions how to curb this error.
I have tried searching for a solution on internet but they were using JSP which I haven't studied yet.
You can get the value submitted from the view to the controller in many ways. As you have a single value is passed from View to Controller you can use
#RequestParam
Your viewMission may look like this
#GetMapping("/viewMission")
public String viewMission2(#RequestParam#RequestParam(name = "agents", required = true) String agents, Model model) {
List<Mission> mission1 = database.getMissions(String agents);
model.addAttribute("missionList", mission1);
return "view_missions";
}
You have to pass the selected value to your query to filter the list based on the selected agent and your query will be
public List<Mission> getMissions(String agents) {
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
String query = "SELECT * FROM missions WHERE agent ='" + agent +"'";
BeanPropertyRowMapper<Mission> missionMapper = new BeanPropertyRowMapper<Mission>(Mission.class);
List<Mission> missions = jdbc.query(query, namedParameters, missionMapper);
return missions;
}
Which will filter the list.
I have an object inside an IEnumerable of my model class, the rendered HTML looks like
<input data-val="true" data-val-number="The field money must be a number." data-val-remote="'money' is invalid." data-val-remote-additionalfields="*.money" data-val-remote-url="/RemoteValidator/ValidateMoney" data-val-required="The money field is required." id="BudgetDetails_0__BudgetData_Money" name="BudgetDetails[0].BudgetData.Money" type="text" value="100" />
<span class="field-validation-valid" data-valmsg-for="BudgetDetails[0].BudgetData.Money" data-valmsg-replace="true"></span>
The model classes look like
public class MyViewModel
{
public IEnumerable<Budget> BudgetDetails { get; set; }
}
public class Budget
{
public int SomeIdentifier { get; set; }
public BudgetValues BudgetData { get; set; }
}
public class BudgetValues
{
[Remote("ValidateMoney", "RemoteValidator")]
public decimal? Money { get; set; }
// other properties
}
View is
#model DictionaryAndRemote.Models.MyViewModel
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
<script src="#Url.Content("~/Scripts/jquery-1.5.1.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
</head>
<body>
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.BudgetDetails)
<br />
<input type="submit" value="Submit user Data" />
}
</body>
</html>
The edit template Views\Shared\EditorTemplates\Budget.cshtml is
#model DictionaryAndRemote.Models.Budget
<div id="#Model.SomeIdentifier.ToString()">
<div>
#Html.TextBoxFor(x => x.BudgetData.Money)
#Html.ValidationMessageFor(x => x.BudgetData.Money)
</div>
</div>
The UI will trigger Ajax call http://localhost:4276/RemoteValidator/ValidateMoney?BudgetDetails%5B0%5D.BudgetData.Money=500 but unfortunately routing table is unable to match the request to my action method
public ActionResult ValidateMoney(decimal money)
{
return Json("I will always fail you.", JsonRequestBehavior.AllowGet);
}
Because the parameter name does not match. Since is is inside an IEnumerable the parameter name is even dynamic BudgetDetails[0].BudgetData.Money, BudgetDetails[1].BudgetData.Moneyand so on.
Of course I always can tweak action medhod to be
public ActionResult ValidateMoney()
{
string parameter = Request.QueryString.ToString();
return Json("I will always fail you.", JsonRequestBehavior.AllowGet);
}
And use very primitive way to parse query string, but I don't think it is the most elegant solution.
Anybody has some experience to share?
Try this way.
public JsonResult ValidateMoney([Bind(Include = "Money")]BudgetValues budgetValues)
{
if(null != budgetValues)
{
decimal money = budgetValues.Money
}
return Json("I will always fail you.", JsonRequestBehavior.AllowGet);
}