As we all know RenderAction() is either part of:
Asp.net MVC 1 Futures or
Asp.net MVC 2 Beta 2
and allows us to render action result inside another view or partial view.
Description
You have a view with multiple partial views displayed using RenderAction() helper.
At least two partial views render a <form> probably by using Html.BeginForm() that postback to original view.
Postback is not performed via Ajax call
Postback data is validated upon form POST.
Problem
When one of the forms gets posted back the other one renders as invalid.
Has anyone used this pattern and solved it? We should somehow know which form performed postback and only that one should validate its POST data. Others should either ignore validation or perform regular HttpVerb.Get action processing.
Have a hidden field in the form to indicate which one. Or, have a prefix passed to the partial and appended to each element in the form.
About prefixes. First way is to have two properties, calling Html.RenderPartial("partial", Model.Data1/2.WithPrefix("data1")).
public class FormModel
{
public string Prefix { get; set; }
}
public class FormData
{
public FormModel Data1 { get; set; }
public FormModel Data2 { get; set; }
}
public ActionResult HandlePost(FormData data)
{
if (data.Data1 != null) {} else {}
}
Second way is the same but use two action parameters.
public ActionResult HandlePost(FormModel data1, FormModel data2)
{
if (data1 != null) {} else {}
}
In the partial view you do
<%= Html.TextBox(Model.Prefix + ".FormModelField", Model.FormModelField) %>
that is, you set field name with the prefix passed in the model.
Of course you may vary this in details.
Related
I am creating simple mvc application using c#.
when I use Partial view to get the input the validation is not triggered.I have done the validation using data annotation .And another thing I am not using any form element in the partial view
What is the solution for the Kindly give the suggestion to this
So, I assume you a building a form you would like to submit.
First of all, you will suggest to you use EditorTemplates and not partial views. But this is just a tip.
Here is an example of loading partial view and resetting validation
$("#btnNewOrderLine").click(e => {
e.preventDefault();
(<any>$('#modalEditOrderLine')).modal('show');
var orderId = $("#OrderID").val();
$('#modalOrderLineBody').load("/ExactSalesOrders/PartialOrderLineDetail/", { orderLineId: "new", orderId: orderId },
() => {
$('#formOLDetail').removeData('validator');
$('#formOLDetail').removeData('unobtrusiveValidation');
$("#formOLDetail").each(function () { $.data($(this)[0], 'validator', false); }); //enable to display the error messages
$.validator.unobtrusive.parse("#formOLDetail");
}
);
});
Edit: you don't need to add any scripts to the end of the partialview page
See your ViewModal should contain all the Properties including the properties you are showing in Partial View. And you should include Data Annotation attribute to the required properties.
For Example:
public class myViewModal
{
[Required]
public int Id{get;set;}
[Required]
public string Name{get;set;}
public string Desc{get;set;}
//These two properties are for partial view
[Required]
public string DOB{get;set;}
[Required]
public string AnyOtherField{get;set;}
}
You should reference this model in your main view
#model MyProject.Model.myViewModal
Then Inside BeginForm or Form Tag in main view, you need to render the partial view to work validation.
#HTML.Beginform()
{
// My main View HTML goes here
// Here call the partial view
}
Alright...this may be a bit backwards but, I only need to do it in one spot.
I have a Model
public class LoginModel : xxx.Models.PageVars
{
public Item.LoginAttempt LoginAttempt { get; set; }
public LoginModel()
{
// does a bunch of stuff here...mainly to set the layout properties from PageVar
this.LoginAttempt = new Item.LoginAttempt();
}
}
Login Attempt is a simple obj (for now)
// login attempt
public class LoginAttempt
{
public string Email { get; set; }
public string Password { get; set; }
}
My controller
public ActionResult Login()
{
return View("Login", new Models.LoginModel());
}
[HttpPost]
public ActionResult LoginAttempt(LoginAttempt model)
{
return View("Login", model);
}
In my view
#model xxx.Models.LoginModel
Is there a way to use the property of the obj/model from LoginModel for the #model.
I can get the values from FormCollection or request but...that's not optimal.
thoughts???
tnx
The model for your GET should match the model for your POST. Otherwise, you're not playing on the same field. In order to allow the binding of data from a POST to a model, the HTML Helpers will generate a name that matches the access path of the property in the view's model. In other words, in your form, based on the model being LoginModel, your field names will be LoginAttempt.Email and LoginAttempt.Password. But, in the POST action, you're accepting just LoginAttempt, so the modelbinder is expecting to see data for Email and Password, which it won't find.
There's actually not even any need for this nested class. Just put your Email and Password fields directly on LoginModel and use that for both your view and your POST parameter. Then, you won't have any issues because everything will match up.
Why don't you have the form post controller action accept the parent model LoginModel instead of LoginAttempt? That way, the default MVC model binding should automatically parse the submitted values into the LoginModel and you'll have acces to LoginAttempt.
If it isn't then your form needs to use the prefix values in the names of the properties on the form. This is done automatically when you use TextboxFor, DropdownListFor etc.
In your example, the names of the form fields should start with LoginAttempt.Email etc
I've seen it work 2 ways. First way would be to rename your LoginAttempt model parameter to be
[HttpPost]
public ActionResult LoginAttempt(LoginAttempt loginModel)
{
return View("Login", model);
}
But i would use the Bind(Prefix) option
[HttpPost]
public ActionResult LoginAttempt([Bind(Prefix="LoginModel")] LoginAttempt model)
{
return View("Login", model);
}
you can't really return model of type LoginAttempt to the view though so you'd have to do even more work to get it to work if you're set on doing it this way. You should probably be redirecting to a different page instead of returning the Login view if it succeeds. Other wise return new LoginModel() {LoginAttempt = model}
I am in the process of migrating PHP code to ASP.NET MVC and previously for the register page I would store if the new user had accepted the rules and also was COPPA verified by redirecting from /register to /register&readrules=1&coppa=1. I would then just parse the #readrules and #coppa in the code.
What is the best way to do this in ASP.NET? Thanks
Use query string parameters instead:
/register?readrules=1&coppa=1
This is more standard and you do not need any parsing. Just define a view model to accomodate those values:
public class MyViewModel
{
public int Readrules { get; set; }
public int Coppa { get; set; }
}
and ten have your Register controller action take this view model as parameter:
public ActionResult Register(MyViewModel model)
{
... at this stage model.Readrules and model.Coppa will contain the values passed
as query string parameters tat you could use here
}
The default model binder will automatically bind the values of the readrules and coppa query string parameters to the corresponding properties of the view model that your controller action takes.
I'm new to asp.net mvc. Basically i'm from php programmer. In my php file i can display what are all the values coming from html page or form using echo $_POST; or print_r($_POST); or var_dump($_POST). But in asp.net how can i achieve this to check what are all the values are coming from UI Page to controller.
You may take a look at the Request.Form property:
public ActionResult SomeAction()
{
var values = Request.Form;
...
}
You could put a breakpoint and analyze the values. Or simply use a javascript development toolbar in your browser (such as FireBug or Chrome Developer Toolbar) to see exactly what gets sent to the server.
But normally you are not supposed to directly access the raw values. In ASP.NET MVC there's a model binder which could instantiate some model based on the values sent to the server.
For example you could have the following model:
public class MyViewModel
{
public int Age { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
and then have your controller action take this model as parameter:
public ActionResult SomeAction(MyViewModel model)
{
... you could use the model properties here
}
and now you could invoke this controller action either wityh a GET request passing the parameters in the query string (/someaction?age=10&firstname=foo&lastname=bar) or using a POST and sending them in the body.
You can check the raw data via Request.Form.
But this is not he spirit of the ASP.NET MVC. It is preferd that you expect a model into your controller. You have all type safety mapping already done by special module called model binder.
So unless you work on some special case, you just add a model to the controller action:
public ActionResult SomeAction(SomeModel model)
{
//Handle SomeModel data further ...
}
You can create an action which will accept the parameters from the UI page like the following:
[HttpPost]
public ActionResult SomeAction(string param1, int param2)
{
//Now you can access the values here
}
or make an action which will accept the model
public ActionResult SomeAction(SomeModel model)
{
//Access the model here
}
Consider the following scenario:
Action Edit() is forwarded to Edit.aspx view to render the view.
Edit.aspx consists of textbox1 and two partial views (aka view user controls):
part1.ascx (which has textbox2, textbox3)
and part2.ascx (which has checkbox1 and checkbox2)
You want to have a strongly typed view for Edit.aspx, say, you use EditViewData class.
You also need Edit.aspx, part1.ascx and part2.ascx have access to some global information such as currentUserID, currentUserLanguage, currentUserTimezone.
Questions:
How do you go about structuring the EditViewData class?
How do you pass the view data to the view and partial views so that the object gets populated automatically when you submit the form and return to the Edit() http.post action?
What do you pass to the Edit() http.post action?
Your viewdata should look like this:
public class EditViewData
{
public int currentUserID { get; set; }
public string currentUserLanguage { get; set; }
public string currentUserTimezone { get; set; }
// ... other stuff
}
After you strongly type your aspx, you also need to strongly type your ascxs. Then in your aspx, when you call RenderPartial, just call like usual:
<% using (Html.BeginForm()) %>
<% Html.RenderPartial("part1.ascx" ); %>
<% Html.RenderPartial("part2.ascx" ); %>
<%}%>
It should automatically inherit the Model in the control. Just remember that your BeginForm should be surrounding both of your controls (ascxs).