Trigger multiple actions from a single request in Struts - struts

I'm new with structs, so pardon if I'm not using the correct terms or being too vague.
I have multiple forms on a page. I have each form's action property tied to separate actions in struts-config. Each form's submission works correctly. But I'd also like to prepopulate all of the forms when the page loads.
I tried creating multiple s in struts config, all with the same path but each with different type properties. But only the final seems to be executed. Is there a way I can make all of these actions execute, or is there some way to make an action trigger other actions, or something like that? I would just make one setup controller, but you can only tie a single form to an action, so I don't think that would work.
I think I'm using Struts 1.

Not sure if your form data is related, but even if its not, but one strategy that can work is implementing a base data, eg:
public class DataAction extends ActionSupport
{
private Data1 data1 = new Data1() // or whatever strategy of populating data
public Data1 getData() { return data1 }
public void execute()
{
// any common execution code
}
}
and then extend the action for each form
public class Form1Action extends DataAction
{
public void execute()
{
super.execute();
// unique execution code
}
}
then from your jsp page, just call the data object(s) for each form, as they will be inherited form the base class. For situations where you don't want to load a data object on each request of the Action, you can simply use some logic in the base Data class and have the extending class use that logic to decide whether or not to prepopulate that data object.
Another strategy, is to have an individual Action process all your forms. Again this only makes sense depending on your data and your design. If they aren't logically related, don't merge them into a single action.

Related

How can I make data from form1 accessible to form2 in different post events for razor pages without the use of static types?

I am essentially trying to access data from form1 in form2 post event handler. I have two forms on the same page with two different post event handlers that trigger based on which button is pressed. My issue here is, once my second post event handler is trigger all of the data from form1 becomes out of scope and inaccessible. The only way so far I was able to make this work is by using static types but I would prefer not to use static types as they can cause problems if not handled properly. I have provided a code snippet of what I am essentially trying to accomplish. I have looked at other posts but I can't find one similar to my scenario.
public PageProperty form1; //I can switch this to static type to accomplish my needs but I am trying to find a better way to do this.
public void OnPostSubmitForm1(PageProperty form1Data)
{
form1 = form1Data; //gives form1 data
}
public void OnPostSubmitForm2(PageProperty form2Data)
{
PageProperty form2 = form1; //comes back as null if I don't use static type
}
You need to save the Form One data somewhere. Instead of trying to save it statically server-side, you could save it in your browser's Local Store and then submit it with your form2 data.

Accessing controls in Razor view from controller MVC4

I am new to MVC. In my application the view page created using razor by designing it from another html page designer. I have doubt that how to access the html controls from the corresponding controller. For example, i create a controller named Home and and corresponding view. Added a text box into it.
<input id="name" type="text" name="txtName"/>
Now i want to get and set the value in text box from controller without using script.
Just like
txtName.text="...."
Is that possible..?
It sounds like you are thinking of things from a Web Forms perspective, e.g. controls, setting properties server-side.
MVC allows much better separation of concerns, that is, each piece should play its part without being tightly coupled to other parts. Having a controller set a property of a textbox in a view means that there must always be a textbox in that view and would tightly couple the controller to that particular view. It is not directly possible and it would be a bad idea even if it was.
That's where view models come in:
// M - model
public sealed class MyViewModel
{
public string Name { get; set; }
}
// V - view
#model MyViewModel
// (usually code to begin a form goes here)
#Html.TextBoxFor( o => o.Name )
// C - controller
public ActionResult MyActionMethod()
{
var model = new MyViewModel { Name = "Hello" };
return View( model );
}
It may seem like an extra step (it is) but it is cleaner, far more flexible, and far more test-friendly.
It would only be possible with another request to the server (e.g. POST, GET) because the Controller code can only run server-side. After processing another request, you could use a ViewModel to populate your HTML text-box while rendering it, but I doubt that is what you are looking for.
If you are familiar with desktop programming (e.g. Window's Forms) and you are looking to immediately change and process fields on an HTML page, you will need to use JavaScript. If you are unfamiliar with web-programming, or even just new to the MVC paradigm, I suggest you try out a few MSDN tutorials.

Html.RenderAction uses Post instead of Get

I have a simple form on my page. When submitted, it checks if ModelState.IsValid and returns the View with the same model if it's not valid.
On the same page, I'm rendering an action that contains another form like so:
Html.RenderAction("AccountNote", new { id = Model.ID });
Everything works fine until I submit the form on my page and the validation fails. When it shows the page again, the AccountNote action's Post event fires when I'd expect the Get event to fire. I guess it makes sense why it's happening since it's the post that action that's rendering the view, but I want the Get event to fire instead.
public ActionResult AccountNote(int id)
{
//code goes here...
return PartialView(model);
}
[HttpPost]
public ActionResult AccountNote(AccountNoteViewModel model)
{
//code goes here...
return PartialView(model);
}
Am I doing something incorrect? Or is there some trickery I have to do to make this work? I would expect the Html.RenderAction to always assume GET instead of POST.
One solution would be to have only one AccountNote() action method. Then it will be called regardless of GET or POST. You might have to modify your logic a bit if you were using POST version of AccountNote().
And you can decorate it with [ChildActionOnly] attribute.
Since I know, there is not any solution for this problem out of the box. RenderAction and Action methods, consider the current request for deciding on to use which verb.
But you can rename them. For example rename the one that is restricted to HttpPost to AddAccountNote and leave the other one with the current name and without specifying its verb.
Would RenderPartial be an option for you?
More discussion on this topic can be found here: RenderAction calls wrong action method

How to expose and call methods on MVC 4 user controls

I am converting my asp.net site to MVC 4. My site has a control called loginbox that prompts the user for username and password. The control also exposes a method called IsLoggedIn that a hosting page can call. I want to continue to encapsulate the login logic in my loginbox control and call it in a similar fashion from a parent level page (i.e loginBoxInstance.IsLoggedIn()). How do I do that?
MVC doesn't have a concept of user controls. The whole setup of MVC is to separate logic from the view. You could achieve a similar setup by creating a separate controller and a partial view.
Then in your main view you could call RenderAction on the controller, which renders the partial view. However, this is only valid for the rendering stage, so something like IsLoggedIn() is not something you can (or should) do in MVC.
Example:
Controller
public class LoginController
{
public ActionResult Login()
{
return PartialView();
}
}
Partial View
// Place this file in Views/Login/Login.cshtml
<div>
<!-- Your markup -->
</div>
Main view
#Html.RenderAction("Login", "Login")
This will allow you to separate the view part (and also the logic) of the login rendering into a separate controller and view, which can be included in another view.
However, what you probably want is something like Action-attributes or inherit from a base controller class which handles all this for you.
The paradigm of MVC versus Web Forms is very different, and I think you should look into a more appropriate way of doing this.

ASP.NET MVC ViewModel inheritance issue

I have the following ViewModels :
public class MyViewModel
{
public BaseViewModel mySubViewModel;
}
public class ChildViewModel: BaseViewModel
{}
I then create a MyViewModel model, which contains a property of type ChildViewModel. In the View, it is displayed just fine.
Then I hit the save button to submit changes to my Model and I call the following controller:
[HttpPost]
public ActionResult Edit(MyViewModel model)
{
return null;
}
To my surprise, the property mySubViewModel is now of type BaseViewModel instead of ChildViewModel ! I have no idea what's going on here. What am I doing wrong ?
To my surprise, the property mySubViewModel is now of type
BaseViewModel instead of ChildViewModel ! I have no idea what's going
on here. What am I doing wrong ?
You shouldn't be surprised by that. You are doing nothing wrong. This is by design. The default model binder sees that your controller action is taking a MyViewModel argument and is attempting to bind the contents of the POST request to it. The default model binder has absolutely no way of knowing that you might have written some derived classes (such as ChildViewModel in your case) and that you want those derived classes to be used instantiated here. The fact that you have passed this concrete view model instance from your GET action to the view has no influence to the POST action. Think of it in terms of HTTP and what the default model binder sees. Think for example that this POST action could be invoked from some completely different client and not from a form submission. Could be for example an iPhone application performing an HTTP request to the POST action. See, now it makes perfect sense. The default model binder can only see the payload of the POST request and the type you specified as action argument. And that's what he does => it instantiates this types and binds its properties from the POST payload data.
So one possibility is to write a custom model binder that will instantiate the concrete instance of your view model you wish. I have exemplified such a custom model binder at this post. In this example I have included a hidden field inside the form that will contain the concrete type of the view model that we would like to be instantiated and then the custom model binder simply uses this information to create this type at runtime.