How do you set/get multiple values from a single jsp page to and from java - javabeans

Apologize in advance if my terminology is confusing or incorrect, beginner with jsp. I'm attempting to create a jsp page where the user is prompted for their hobby through radio buttons (Boxing, MMA, Street Fighting) and their name ("John Doe"). I want to pass both values into Java and run some 'if then' statements based on their radio button responses then print out something like:
John "MMA" Doe "Make sure you ground and pound"
or
Mary "The Boxer" Jones "Remember to keep your hands up"
Not too worried about the if then statement, but getting confused as to how to pass multiple values to and from jsp and java)
Currently able to only pass back the 'name' value. Hobby remains 'null'.
Three parts to the code below: index.jsp, Response.jsp, Hobby1.java
I suspect I'm doing multiple things incorrectly and that there is an easier way of doing this.
index.jsp
<form name="Hobby" action="response.jsp">
<input type="radio" name=”hobby” checked=yes value="Boxing"/>Boxing
<input type="radio" name=”hobby” value="MMA"/>MMA
<input type="radio" name=”hobby” value="StreetFight"/>Street Fighting
<br>
Enter Name:
<input type="text" name="name" value="" />
<input type="submit" value="Submit" />
</form>
Response.jsp
<body>
<jsp:useBean id="mybean" scope="session" class="org.Hobby.test.Hobby1" />
<jsp:setProperty name="mybean" property="hobby" />
<jsp:setProperty name="mybean" property="name" />
<br>
<jsp:getProperty name="mybean" property="hobby" />
<jsp:getProperty name="mybean" property="name" /
Class Hobby1
public class Hobby1 {
private String name;
private String hobby;
String baseText;
public Hobby1()
{
hobby = null;
name = null;
}
/**
* #return the name
*/
public String getName()
{
String temp;
temp = method(name); //basically want a method which goes through the if-then logic mentioned above
return temp;
}
/**
* #param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
public void setHobby(String hobby)
{
this.hobby = hobby;
}
public String getHobby()
{
String temp;
temp = hobby;
return temp;
}

OP here:
Due to inexperience, I was approaching this all wrong and the title was incorrect.
The title should have been: How do I pass radio buttons values from a jsp page to a servlet.
Initial goal: I was attempting to pass radio button values to a 'regular' java class, not a java servlet class and failed to understand the difference.
Resolution:
-removed response.jsp
-added "method="get" to the jsp Action and created a new servlet class utilizing "protected void doPost" and "String radioButton=request.getParameter" to evaluate the radio button values.
This resolved my issue.

Related

How do i get the URL from the caller of a HTTP Request?

Let's say that i have a navbar with a search bar, and it appears on every single page, so when the user click on the search button, it could happend 2 things:
Refresh the page if the input is empty
Redirect to a SearchResult.cshtml and show the results...
So the controller and action who handle the HTTP POST Request are Search - SearchResult respectively. I want to get the URL from the caller because the action method will need it to decide what page should redirect it.
PD: I'm using ASP.NET CORE MVC 3.1
In the Layout page, you could add a hidden field to store the current page URL, then, when click the Search button, in the SearchResult action, you could get the previous URL from the hidden field. Code as below:
_Layout.cshtml page,
<div class="search">
#{
//get current url
Uri currenturl = new Uri(String.Format("{0}://{1}{2}{3}", Context.Request.Scheme, Context.Request.Host, Context.Request.Path, Context.Request.QueryString));
}
<form asp-controller="Search" asp-action="SearchResult">
<input class="text-body" type="text" value="" name="search" />
<input name="returnurl" type="hidden" value="#currenturl" />
<input type="submit" class="btn btn-info" value="Search" />
</form>
</div>
Code in the SearchResult action:
public IActionResult SearchResult()
{
//get the returned url
var returnurl = HttpContext.Request.Form["returnurl"].ToString();
//do something
return Redirect(returnurl);
}
The screenshot as below:
What you probably want to do is submit the current path/query along with your query.
You could accomplish that by having your search form be something like this.
<form asp-controller="Search" method="get">
<input name="q" value="#Context.Request.Query["q"]" />
<input name="r" type="hidden" value="#Context.Request.GetEncodedPathAndQuery()" placeholder="Search the thing" />
</form>
Notice im using a get method here. This is to keep the search state in the browser but you can manage that however you need too. Im also using GetEncodedPathAndQuery which will need to be installed, but again the important part is to maintain the path/query(and more if this will be cross domain).
My controller will then look something like this.
[Route("/search")]
public class SearchController : Controller
{
[HttpGet]
public IActionResult Index(
[Bind(Prefix = "q")] string query,
[Bind(Prefix = "r")] string referrer)
{
IActionResult result = null;
if (string.IsNullOrWhiteSpace(query))
{
result = this.Redirect(referrer);
}
else
{
result = this.View(); // do search and return view.
}
return result ?? this.Redirect("/");
}
}
This can obviously be adjusted in anyway you need. The main thing is accepting the two values from the request and handling them properly. You might also want to validate that the referrer is an actual url since the redirect action will throw if its not.

NetCore InputTagHelper using reflection

I have a model with lots of properties. Creating or updating theirs views is a troublesome work.
So i trying to use Reflection to create view during runtime:
(PS: yes, i know the front-end is very import, i should use Vue or other frame to create views at designtime. But I just want to try buildering forms at runtime, yes i am a freak. LOL)
There is my code:
#{
var dic = Model.GetAttributePropsByCategory();// get PropertyInfo by CategoryAttribute and custom DisplayIndexAttribute
}
#foreach (var items in dic)
{
var category = items.Key; // InfoCategoryAttribute
foreach (var tuple in items.Value)
{
var displayIndex = tuple.Item1; // Custom: DisplayIndexAttribute
var prop = tuple.Item2; // PropertyInfo
<input asp-for="#prop.Name" class="form-control"/>
}
}
My target is:
<input class="form-control valid" type="text" data-val="true" data-val-required="The VIN field is required." id="VIN" name="VIN" value="VIN001" aria-describedby="VIN-error" aria-invalid="false">
But the result like this:
<input class="form-control valid" type="text" data-val="true" data-val-required="The Name field is required." id="prop_Name" name="prop.Name" aria-describedby="prop_Name-error" aria-invalid="false">
So, I read the source code in the aspnetcore.mvc.taghelpers. I found the key is InputTagHelper.For:
public class InputTagHelper : TagHelper
{
...
[HtmlAttributeName(ForAttributeName)]
public ModelExpression For { get; set; }
...
}
But I can't understand how the InputTagHelper.For was created. Therefor, i dont know how to override it to achieve my target.
Is there any Suggestions? Thx.
In source code of InputTagHelper, we can find following code snippet will help generate textbox input and the third parameter For.Name would be used to set value(s) of textbox id and name attribute.
return Generator.GenerateTextBox(
ViewContext,
modelExplorer,
For.Name,
modelExplorer.Model,
format,
htmlAttributes);
And if we debug the source code, we will find the value of For look like below.
To achieve your expected result, you can customize it and pass For.Model.ToString() to GenerateTextBox method rather than For.Name, like below.
return Generator.GenerateTextBox(
ViewContext,
modelExplorer,
//For.Name,
For.Model.ToString(),
modelExplorer.Model,
format,
htmlAttributes);
Test Result

How can I post the same data to two different handlers depending on the button clicked?

[See updates at bottom]
I have a Razor page with a form on it. I want to have two buttons on that form, that perform a slightly different action - both using the same posted form data.
I tried using the asp-page-handler helper on the second button, but it doesn't seem to add anything to the HTML (I would expect it to add a formaction attribute to the <button> element, but it doesn't add anything at all).
Here's an example page:
#page "{id?}"
#model IndexModel
#tagHelperPrefix x:
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<p>Current value is #Model.Foo</p>
<x:form method="post">
<input type="text" name="foo" />
<button type="submit">Default</button>
<button type="submit" x:asp-page-handler="Alternative">Alternative</button>
</x:form>
... and here's the corresponding page model:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace MyWebApplication.Pages
{
public class IndexModel : PageModel
{
[BindProperty]
public string Foo { get; set; }
public void OnGet(int? id)
{
}
public void OnPostAsync(string foo)
{
Foo = foo;
}
public void OnPostAlternativeAsync(string foo)
{
Foo = foo.ToUpper();
}
}
}
This is rendered as:
...where the generated HTML for the form is:
<form method="post">
<input type="text" name="foo" />
<button type="submit">Default</button>
<button type="submit" x:asp-page-handler="Alternative">Alternative</button>
</form>
The fact that the x:asp-page-handler attribute is still in the generated HTML makes me think that the Razor engine hasn't recognized it. I've tried taking off the x: prefix, but that didn't help.
What am I doing wrong?
UPDATE
OK, I tried removing the tag prefix and removing the #tagHelperPrefix line, and that made a difference. A formaction is added to the second <button> element as expected.
However:
that's really annoying - the #tagHelperPrefix is not something I want to lose, and
now both buttons are triggering the "Alternative" action, even though only one of them has the formaction!
Here's the new generated HTML:
<form method="post">
<input type="text" name="foo" />
<button type="submit">Default</button>
<button type="submit" formaction="/?handler=Alternative">Alternative</button>
</form>
SECOND UPDATE
OK, so If I put asp-page-handler="" on the "default" button, then each button goes to the correct handler, which is fine.
The last question that remains, then, is: how can I make this work with the tag helper prefix?
[Answering my own question in case this helps others.]
It turns out that:
The tag-helper-prefix only applies to elements, not attributes, so it should be asp-page-handler="..." rather than x:asp-page-handler="..." even if the tag-helper-prefix is x:.
Those asp- attributes are only recognized within a tag that is tag-helper-enabled - which is all elements when no tag-helper-prefix is specified, or only elements with the tag-helper-prefix where one is specified. In my case, I had to change <button ...> to <x:button ...>.
If you specify asp-page-handler for one button, you need to specify it on all the buttons, even if you specify it as "" to get the default action.

How can I render the input with type='text' in blazor server-side?

Here are the codes:
<EditForm OnValidSubmit="#SubmitText" id="inputText">
<InputText #bind-Value="_InputMsgModel.Msg" />
</EditForm>
After the program ran, it turned out to be this:
<form id="inputText">
<input class="valid">
</form>
Now I wanna add an attribute type="text" to the input element, how can I achieve this?
I tried to modify the code like this:
<EditForm OnValidSubmit="#SubmitText" id="inputText">
<input type="text" #bind-Value="_InputMsgModel.Msg" />
</EditForm>
Meanwhile, now visual studio reports an error:
I can not bind the model anymore.
I need to set the type to text for needing to set the keyboard in mobile correctly.
How can I solve this? Thank you.
What is wrong with this code:
<EditForm Model="#_InputMsgModel" OnValidSubmit="#SubmitText" id="inputText" >
<InputText #bind-Value="#_InputMsgModel.Msg" />
</EditForm>
Run this code with the above:
#code {
InputMsgModel _InputMsgModel = new InputMsgModel();
private void SubmitText()
{
Console.WriteLine(_InputMsgModel.Msg);
}
public class InputMsgModel
{
public string Msg { get; set; } = "My new message";
}
}
Do you see the text "My new message" in the text box ? I believe you do... All is well, and the two-way binding mechanism works well. Go and see now the Html...it's still <input class="valid"> which does not reflect the real state of the text box. Think about it...
Update: Of course you can use the following:
<EditForm Model="#_InputMsgModel" OnValidSubmit="#SubmitText" id="inputText" >
<input type="text" #bind-value="#_InputMsgModel.Msg" />
</EditForm>
Important: The error "The attribute names could not..." is triggered because you use capital "V" in #bind-Value. You should use lower case: #bind-value. This is because your using input 'Html element' here, and it has a value attribute, not a Value attribute. But when you use the InputText Component, the capital Value in #bind-Value refers to a Value property defined in the component.

How Can ignore # in Pattern in MVC

I want write pattern to my textbox in view
this textbox will hold email value
but i want write RegEx but i received error because RegEx contains #
i wrote ## but still doesn't work
My Code
<input type="text" name="Emails" id="Emails" class="form-control Div-heigh" placeholder="To...." required pattern="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?" />
I'd look to create a HTML Helper, like so;
public static class ValidationExtensions
{
public static string EmailRegex(this HtmlHelper helper)
{
return #"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
}
}
Then use it in your view;
<input requiredPattern="#Html.EmailRegex()" />
This will be re-useable between views and separate a complex regex (a programmer artefact) from html (more of a designer task).
EDIT: link to a longer article about creating helpers.