In struts2 actions the injection is used for setting the property values of an action class, so the properties are updated by form fields on the form submission. To discover which form is submitted I create a method calling isFormSubmitted() and in there I check a redundant property created only for this motive. The property is updated in a hidden field. But I find this workout so dirty! I think that there must be a better way to solve this problem.
What I do is:
<s:form name="form1">
<s:hidden name="submit" value="10" />
...other fields go here
</s:form>
in the action class I have getSubmit, setSubmit methods and the following method:
public boolean isFormSubmitted(){
return (submit == 10);
}
Your can call different action methods in your action, not only "execute" method. Just put the parameter with the name like "method:actionMethodName" in your request. Here is example:
public class MyAction extends ActionSupport {
public String execute() {
// Base code
return SUCCESS;
}
public String one() {
// Code one
return SUCCESS;
}
public String two() {
// Code two
return SUCCESS;
}
}
And here is jsp:
<s:form action="MyAction">
<input type="submit" value="Call execute"/>
<input type="submit" name="method:one" value="Call method one"/>
<input type="submit" name="method:two" value="Call method two"/>
</s:>
Or you can do it like this:
<s:form action="MyAction" name="form0">
<!-- call execute-->
</s:>
<s:form action="MyAction" name="form1">
<!-- call method one-->
<input type="hidden" name="method:one"/>
</s:>
<s:form action="MyAction" name="form2">
<!-- call method two-->
<input type="hidden" name="method:two"/>
</s:>
You should use <s:form> tag action attribute to submit to specific action.
<s:form action="action1">
...
</s:form>
<s:form action="action2">
...
</s:form>
See the <s:form> tag documentation: http://struts.apache.org/2.x/docs/form.html.
Update
Then just use separate actions for loading and saving the user.
you should do the submission of the form something like this.
<s:form name="form1">
<s:hidden name="submit" value="10" />
</s:form>
create a java script function
function onclick()
{
document.form1.submit();
}
then create getters & setters in action for hidden field
and in execute method
public String execute()
{
setSubmit(10);
return SUCCESS;
}
Update :
or
<s:a href="your_action"></a>
Related
I have next form:
<form asp-controller="Chat" asp-action="AddFile" method="post" asp-route-chatId="#Model.ChatId" enctype="multipart/form-data">
<textarea id="messageInput" class="textInput" style="width: 80vh" name="messageInput"></textarea>
<div>
<input type="submit" id="sendButton" value="Send Message" />
<input type="file" class="inputfile " id="File" name="File" value="File"/>
<label for="File">Choose a file</label>
</div>
</form>
ViewModel
public class ChatFileViewModel
{
public long ChatId { get; set; }
public string messageInput { get; set; }
public IFormFile File { get; set; }
}
and post method:
[HttpPost]
public void AddFile([FromBody] ChatFileViewModel chatFile)
{ ... }
The issue is - every time i press submit it transfers ChatId correctly, while messageInput and File are null. I have no idea what it is, because i have exactly the same construction working correctly in the other part of my app.
Using [FromBody] To force Web API to read a simple type from the request body, but your object is complex contain string and int can not treat as simple type.
Remove FormBody, I reproduce and it worked
More about FormBody at https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
You should remove the [FromBody] attribute, since your request data is in the form. [FromBody] is usually used to deal with data in the request body like JSON and XML
[HttpPost]
public void AddFile(ChatFileViewModel chatFile)
{ ... }
For more details, you can refer to Model binding.
if you need of want to specify binding then you can use [FromForm] because you correctly setup for into multipart/form-data but it depends on your other actions
public IActionResult AddFile([FromForm]ChatFileViewModel model)
if you use asp- tag helpers you can use them for controls as well
<form asp-controller="Home" asp-action="AddFile" method="post" asp-route-chatId="#Model.ChatId" enctype="multipart/form-data">
<textarea asp-for="messageInput" class="textInput" style="width: 80vh" name="messageInput"></textarea>
<div>
<input type="submit" id="sendButton" value="Send Message" />
<input type="file" class="inputfile " asp-for="File" />
<label asp-for="File">Choose a file</label>
</div>
</form>
I need to pass some flag into a view and get it back.
But requirements are:
this flag is not part of model
and it must not be stored in session or such.
I mean - flag visibility scope should be - current page for current user only.
I tried to put it into a ViewBag like this:
public ActionResult Product_Add()
{
ViewBag.IsNew = true;
ViewData["IsNew"] = ViewBag.IsNew;
ViewBag.RecordActionName = "Add";
return View("Product_Edit");
}
And then use this code in *.cshtml:
<input type="hidden" name="IsNew1" value="#ViewBag.IsNew" />
<input type="hidden" name="IsNew2" value='#ViewData["IsNew"]' />
But in resulting HTML I see this:
<input type="hidden" name="IsNew1" value="value" />
<input type="hidden" name="IsNew2" value='value' />
Then I tried this code in *.cshtml:
#{ string isNewRec = ViewBag.IsNew.ToString(); }
<input type="hidden" name="IsNew1" value="#isNewRec" />
And now it works:
<input type="hidden" name="IsNew1" value="True" />
Question is - why first attempt put "value" text instead of boolean value into HTML?
Also the strange thing - this code works fine:
<input type="hidden" name="ProductID" value="#ViewBag.ProductID" />
So, for integer values in ViewBug it works, returns an actual interger value, but for boolean it returns "value" text.
Another part of question.
Currently I use code like this:
[HttpPost]
public ActionResult Product_Commit(Product pProduct)
{
if (ModelState.IsValid)
{
AbcProducts ctx = new AbcProducts();
bool isNew = Convert.ToBoolean(Request.Form["IsNew"]);
if (isNew)
ctx.Products.Add(pProduct);
else
{
// [...]
}
ctx.SaveChanges();
}
return View();
}
Could you recommend something more correct from MVC point of view to pass non-model parameter into a view and get it back then with submited data?
But this parameter should not be stored anywhere where other pages can see it somehow.
I'm trying to set parameter value bulkID from form in ftl file to action class, but unable to set. Following is the code:
struts.xml file
<action name="bulk" class="com.action.BulkChangeMainAction">
<result name="input" type="freemarker">/resources/templates/bulk-changes.ftl</result>
</action>
BulkChangeMainAction.java
public class BulkChangeMainAction {
private int bulkID;
public int getBulkID() {
return bulkID;
}
public void setBulkID(int bulkID) {
this.bulkID = bulkID;
}
public String input() {
return INPUT;
}
}
bulk-changes.ftl
<form id='filter-form' action="<#s.url action='bulk' method='input'/>" method="post" name="filterForm">
<input type="text" id="bulkID" name="bulkID"/>
<input type="submit" value="Go"/>
</form>
Try using the struts2 form tag and sth like the following (I assume input is the action you want to call?):
<s:form action="bulk.input.action" method="post">
<s:textfield name="bulkId" label="Bulk Id" />
<s:submit value="Confirm" />
</s:form>
Here is a nice complete example too:
http://www.codejava.net/frameworks/struts/handling-form-data-in-struts2
if you need to keep the current format you have, please try changing int to String or Integer and see if it works.
I have a form that has a hidden field wich stores a object. This object is a RoutesValues (I want to store a reference because when I process the form I want to redirect to a route). The action that processes the form is:
public ActionResult Añadir(string userName, string codigoArticulo, string resultAction, string resultController, object resultRouteValues, int cantidad)
{
processForm(codigoArticulo, cantidad);
if (!ModelState.IsValid)
TempData["Error"] = #ErrorStrings.CantidadMayorQue0;
if (!string.IsNullOrWhiteSpace(resultAction) && !string.IsNullOrWhiteSpace(resultController))
return RedirectToAction(resultAction, resultController, resultRouteValues);
return RedirectToAction("Index", "Busqueda", new {Area = ""});
}
and my form is:
#using (Html.BeginForm("Añadir", "Carrito", FormMethod.Get, new { #class = "afegidorCarrito" }))
{
<fieldset>
<input type="hidden" name="codigoArticulo" value="#Model.CodiArticle" />
<input type="hidden" name="resultController" value="#Model.Controller" />
<input type="hidden" name="resultAction" value="#Model.Action" />
<input type="hidden" name="resultRouteValues" value="#Model.RouteValues" />
<input type="text" name="cantidad" value="1" class="anadirCantidad" />
<input type="submit" />
</fieldset>
}
the problem I have is that resultRouteValues gets passed as a string instead of an object. Is there any way to fix this?
Thanks.
No, there is no easy way if RouteValues is a complex object. You will have to serialize the object into some text representation into this hidden field and then deserialize it back in your controller action. You may take a look at MvcContrib's Html.Serialize helper.
In my Controller in a Asp.net MVC 1 app I want to use UpdateModel to populate a variable with POST data in my controller. I've looked at dozens of examples but even the most basic ones seem to fail silently for me.
Here's a very basic example that's just not working.
What am I doing wrong?
public class TestInfo
{
public string username;
public string email;
}
public class AdminController : Controller
{
public ActionResult TestSubmit()
{
var test = new TestInfo();
UpdateModel(test);//all the properties are still null after this executes
//TryUpdateModel(test); //this returns true but fields / properties all null
return Json(test);
}
}
//Form Code that generates the POST data
<form action="/Admin/TestSubmit" method="post">
<div>
<fieldset>
<legend>Account Information</legend>
<p>
<label for="username">Username:</label>
<input id="username" name="username" type="text" value="" />
</p>
<p>
<label for="email">Email:</label>
<input id="email" name="email" type="text" value="" />
</p>
<p>
<input type="submit" value="Login" />
</p>
</fieldset>
</div>
</form>
It looks like you're trying to get the controller to update the model based on the form elements. Try this instead:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult TestSubmit(TestInfo test)
{
UpdateModel(test);
return Json(test);
}
In your code, you're creating a new TestModel instead of letting the MVC runtime serialize it from the HttpPost. I've let myself get wrapped around the axel on this also, you're not the only one!
make properties of your public field:
public class TestInfo
{
public string username {get;set;}
public string email{get;set;}
}
I'm not too familiar with ASP.NET MVC, but shouldn't your TestSubmit method look more like this:
public ActionResult TestSubmit(TestInfo test)
{
UpdateModel(test);
return Json(test);
}
In the controller you should have two methods, one to respond to the GET, the other, if required is for responding to the POST.
So, firstly have a GET method:
public ActionResult Test ()
{
return View (/* add a TestInfo instance here if you're getting it from somewhere - db etc */);
}
Secondly, you'll need a POST method:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Test (TestInfo test)
{
return Json (test);
}
Notice that there's no UpdateMethod there, the ModelBinder would have done that for you.