I have a controller with the codes like this:
[AcceptVerbs("POST")]
public ActionResult Create(FormCollection collection)
{
//why is that the collection is null?
}
I am calling this action using the ajax.actionlink.
my problem is the collection is null, unlike if i use the submit(input) button
the formcollection has values.
FormCollection has a default binder associated with it which always initializes the collection and you should never get null. It is more likely that you have an empty collection when using Ajax.ActionLink in contrast to when using a form submit button. This is because the ActionLink method doesn't POST any form values when it performs the AJAX request.
You need to use Ajax.BeginForm
Related
I need to pass parameters from a view to control in a form. These parameters are for example a string that is not in a textField. The string is "FATHER" and I send this string from the view to the controller when I click on the submit button in the form. Anyone can suggest how I can do it?
add a hidden input field to your form with a value of "FATHER":
<?= form_hidden('name_of_field', 'FATHER') ?>
and in your controller, get the value when the form is submitted:
$value = $this->input->post('name_of_field');
So if this question is about asp.net MVC ... :
Are you using a strongly typed view, do you have a ViewModel? If so, add a property of type string, say StringToHide, to it, set it to "FATHER" and then, in your form, add
#Html.HiddenFor(StringToHide)
Then the information will be passed to the controller, but it is not editable by the user. And if you're not using a viewmodel yet, well, then you should. It's a clean way to compose all your data when passing from views to controllers and vice versa.
Assuming Asp.net MVC
In View
#{ Html.RenderAction("Menu", "", new { parameterFromView= "FATHER" }); }
In Controller
[HttpPost]
public ActionResult Menu(string parameterFromView)
{
// do whatever
}
In jquery call append the text Father to the URL and accept it in controller.
see code below.
$("#submit").click(funtion(){
window.url = "Controller/Action/" + "Father";
});
I have a link and search button. Clicking on search button posts the page to a predefined action. Now clicking on a link should post the page to another action and should post all the values hidden varible values to another action. Can it be done.
Typically A link will generate an anchor tag and it usually gives you an HTTP GET request. Not the post request. You can supply parameters in your link which will be accepted as the parameters of the action method
#Html.ActionLink("Search","Search","Items",new { #id="nokia" },null);
This will generate a link with a querystring key called id with value nokia.
../Items/Search/nokia
or
../Items/Search?id=nokia
And your action method with id parameter can handle this GET request
public ActionResult Search(string id)
{
//Do whatever you want to do with the value in id. return a view with results
}
IF you really want to do an HTTPPost from a link, You can grab the click event of the link in the javascript and make an httppost call. The below script does that with jQuery library.
$(function(){
$("a").click(function(e){
e.preventDefault();
$.post($(this).attr("href"),function(result){
//do whatever with the results
});
});
});
But make sure you have an HttpPost version of the ActionMethod in your controller to handle this request
[HttpPost]
public ActionResult Search(string id)
{
//This is a POST request.Do whatever you want to do with the value in id. return a view with results
}
You can't use #Html.ActionLink for HTTP POST (edited: unless you use javascript function to submit the form via specifying onClick HtmlAttribute) . You can use submit buttons instead and style them as hyperlinks using jQuery. In this case you should be able to post your model with whatever values.
Alternatively you can use #Ajax.ActionLink and specify AjaxOptions { HttpMethod = "POST" }
I am wondering about a couple variations of forms and partial forms. The submit is on the parent page and I have varied what I pass to the partial view. I have a parent view with a related HomeViewModel (which has public properties Name and public Person Employee {get;set;}
1.) Scenario 1: The main view has something like the following
#model MasterDetailSample.Models.HomeViewModel
#using (Html.BeginForm()) {
<div>
#{Html.RenderPartial("_PersonView", #Model);}
</div>
<input type="submit" value="Save" />
}
In this scenario I am passing to the partial view _PersonView the entire HomeViewModel. Within _PersonView partial view I have to reference a property of the HomeViewModel i.e. Person object via #model.Employee.Name (in this scenario the submit is on the parent form (not within the partial view))
When I hit submit on the form (POST) in the controller i have to access the property of Employee "Name" via the following model.Employee.Name
This seems to work however notice the following variation scenario 2 (where I only pass to the partial the Employee object)
2.) Scenario 2
In this scenario I only want to send the Employee object to the partial view. Again the begin form and submit is on the parent form.
So from the parent form i have
#{Html.RenderPartial("_MasterView", #Model.Employee);}
and so within the partial view i reference the Name property of the Person object via #Employee.Name Now when I submit the form within the controller the Employee object is not available from the auto model binder. I can access the properties via formcollection but not from the model parameter
i.e.
[HttpPost]
public ActionResult Index(ModelViewModel model) {
**//model.Employee is null!**
return View();
}
Why? (is model.Employee null) I would like my partial view to only accept an object of type Person however after submitting from the parent page, the Employee property is null. On the partial view I am using the following on the #model line
#model MasterDetailSample.Models.Person
I would like the partial to only need a Person object to be sent to it, but I would like the submit on the main form. If i do it this way I can re-use the partial view in a few situations however IF i must send HomeViewModel i have significantly limited how I can use this partial view. So, again, I only want to use Person as the model with the partial view but I need to be able to access the properties when submitted from the parent view.
Can this be done? If yes how?
thx
You have a couple of options:
1) One I recommend -> Dont use partial views, instead use EditorFor and create an editor template for Person. With partial views the context is whatever model you pass into the view, this is why your example (1) works and (2) not. However with editor templates the parent context is taken into consideration with the html helpers and will generate the correct input names. Have a look at Darin Dimitrov's answer to a similar question.
2) Use your second example as is, but change the post action to look something like this:
[HttpPost]
public ActionResult Index(ModelViewModel model) {
TryUpdateModel(model.Employee);
**//model.Employee should now be filled!**
return View();
}
3) Use custom html helpers that accepts prefix for input, see this answer I posted a while back for example code. You could then use this inside your partial view.
UPDATE:
My model going into the save method is PartialViewModel, which in the save method, is pushed into the index's ContactViewModel and sent back. This wasn't clear.
I am playing around with MVC3, and have a contact controller with a SaveDetails action. The index cshtml has a partial with a form whose action is pointing to this controller.
When I submit the form not having completed it fully, thereby firing the validation, the url now contains the SaveDetails action name (http://localhost:7401/Contact/SaveDetails).
The form code is:
#using (Html.BeginForm("SaveDetails", "Contact")) {
...
}
The controller action looks like this:
public ActionResult SaveDetails(Models.PartialsViewModel pvm)
{
return View("Index", new ContactViewModel{ PartialsViewModel = pvm } );
}
What am I doing wrong?
The form has the action attribute set to SaveDetails action, so after submit it redirects the browser to this action.
I don' think you are doing anything wrong but I don't think you are able to do what you are tying to achieve. A request has to go somewhere and in mvc the url is used to identify which action you want to perform. If you are not submitting a post back then the url is going to change.
One way to submit the forms to different actions would be using some ajax.
Submitting the form is a POST. You can use an attribute to identify what request method an action should respond to. This means that you can create another action also called Index but give it the [HttpPost] attribute.
[HttpPost]
public ActionResult Index(Models.ContactViewModel cvm)
{
return View();
}
This way it won't display the action in the url.
I'm looking into using partial views in MVC3 using Razor, and I get my partial view to render and it works fine.
What I'd like to do, though, is refresh the parent view when the partial view is submitted.
Code in my parent view to render partial view
<div id="mydiv">
#{ Html.RenderAction("Add", "Request"); }
</div>
Action for parent view is simple,
public ActionResult Index()
{
List<obj> reqs = //some query
return View(reqs);
}
In my partial view's get action I have:
public ActionResult Add()
{
AddRequestViewModel vm = new AddRequestViewModel();
//set some stuff on the VM here
return PartialView(vm);
}
In the post action called by the partial view, if modelstate isn't valid, return PartialView(vm)
If it is valid, I'd like the parent and partial views to refresh.
I tried RedirectToAction, but this can't be called in an action called by a partial, apparently, and I tried return Index();, but this causes an issue with the code used to render the partial view,
Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Collections.Generic.List'1[DatRequests.Models.ReqRequest]', but this dictionary requires a model item of type 'DatRequests.ViewModels.AddRequestViewModel'.
Any suggestions on how to do this would be appreciated. The purpose of the page is to show a list of elements, and the partial contains a form to add a new element to the list.
Edit: The partial's model is different, as it contains data for selection, which is from a db, which is why I tried RenderAction, but I'm not sure if there are other ways of doing this.
When the partial view is submitted normally you submit it to some controller action. You could either submit it using a normal request or an AJAX request. If you use a normal request you could perform a standard redirect to the Index inside the POST controller action that will handle the form submission. If you use AJAX, you could return a JSON result pointing to the url that you want to redirect:
[HttpPost]
public ActionResult Foo(MyViewModel model)
{
if (!ModelState.IsValid)
{
return PartialView(model);
}
return Json(new { url = Url.Action("Index") });
}
and inside your AJAX success callback:
success: function(result) {
if (result.url) {
// we have a success
window.location.href = result.url;
} else {
// invalid modelstate => refresh the partial
$('#mydiv').html(result);
}
}
Probably RenderAction should not be used this way.
When using Html.RenderAction, a new/seperate request would be sent to the server. And you got another chance to load some data from db or somewhere else to display to the client. Also, you could apply OutputCache to this action. this is usually the way doing global cache.
Here you are doing a POST to the server. Either directly put a element here or using a partial view to do the Post. And in the corresponding action, do a RedirectToAction.
Do it with ajax or not isn't the point. my opinion is more about the right way using RenderAction