Posting collections using partial views and microsoft ajax in ASP.Net MVC2 - ajax

I am using the partial view with the ajax.beginform. In that partial view page, i have the following markup
EDIT
<%
using (Ajax.BeginForm("ManageDataSources", "DataSources", saveAjaxOptions))
{
%>....
<td>
<%: Html.Hidden("DataSource_Id", dataSource.Id, new { #class = "DataSource_Id" })%>
<%: Html.TextBox("DataSource_Name", dataSource.Name, new { #class = "DataSource_Name" })%>
</td>
<tr class="queryParameters" style="display: block">
<td colspan="2" align="center">
<input id="Text1" name="parametername" type="text" />
<input id="Text2" name="parametervalue" type="text" />
<input id="Text3" name="parametername" type="text" />
<input id="Text4" name="parametervalue" type="text" />
<input id="Text5" name="parametername" type="text" />
<input id="Text6" name="parametervalue" type="text" />
<input id="Text7" name="parametername" type="text" />
<input id="Text8" name="parametervalue" type="text" />
<input id="Text9" name="parametername" type="text" />
<input id="Text10" name="parametervalue" type="text" />
</td>
</tr>
and in the the controller, i have this model for the representation of the data
public class DataSourceViewModel
{
public string DataSource_Id { get; set; }
public string DataSource_Name { get; set; }
public List<SCParams> parameters { get; set; }
}
public class SCParams
{
public string parametername { get; set; }
public string parametervalue { get; set; }
}
EDIT
public ActionResult ManageDataSources(DataSourceViewModel dsvm)
{
return PartialView("ManageDataSources");
}
when i post the data these parametername and parameter values are not at all bound to the list of objects. How do i do this. i am using microsoft ajax and want to do this without using other plugings. Kindly suggest the right way.
EDIT
This is the data in the header taken from chrome
DataSource_Id:
DataSource_Name:Name
parametername:a
parametervalue:1
parametername:q
parametervalue:2
parametername:z
parametervalue:3
parametername:s
parametervalue:4
parametername:w
parametervalue:5
x:15
y:12

What I understand you have master detail structure and you want to receive it controller. if that is the case. then there are two possibilities either your detail portion has variable length detail portion or fixed length detail portion. You may follow the post here for variable length as well as fixed length. For Fixed length you may also follow here.
You will receive the model in following signature
public ActionResult ManageDataSources(DataSourceViewModel dsvm)
moreover you may also check formcollection parameter for actionresult
[HttpPost]
public ActionResult MyAction(FormCollection collection)

Related

Spring mvc: bind hash map with same/different value depending on user input

I have a requirement where I am asked to capture a fee applicable for a certain course. But the problem is for few courses the same fee is applicable to all type of users and for some courses profession-wise fee is applicable. eg if the user is a teacher then he has fewer fees than if he is an industry professional.
There are predefined professions in database.
Here is my current logic with code.
Depending on the radio button, I am toggling the proper div and particular logic at the back end.
<input type="radio" name="professionWiseFees" value="true">
<input type="radio" name="professionWiseFees" value="false">
<div id="totalAmount" class="hidden">
<input class="feeAmountOnly" name="feeAmount" type="text" />
</div>
<div id="professionWiseAmount" class="hidden">
<c:forEach items="${applicationScope.professionList}" var = "profession" >
Course Fee For ${profession.profession}
<input type="hidden" value="${profession.id}" name="profession" type="text"/>
<input class="feeAmoun2t" name="profession" type="text" />
</c:forEach>
<div>
Now I am checking which type of fees is applicable and filling the hashmap accordingly. if prefessionWiseFees is not applicable then adding the same fees to all the profession.
Boolean isProfessionWiseFeesApplicable = Boolean.parseBoolean(reqParams.get("professionWiseFees")[0]);
Map<Integer,Double> feeProfessionMap = new HashMap<>();
List<Profession> professions = (List<Profession>) servletContext.getAttribute("professionList");
if(isProfessionWiseFeesApplicable) {
String[] propfessionWiseFees = reqParams.get("profession");
// [1(profession_id),1000(fees),2,2000,3,7000], hence i+2 i=profession_id, i+1=fees
for(int i=0; i < propfessionWiseFees.length-1 ;i=i+2){
feeProfessionMap.put(Integer.valueOf(propfessionWiseFees[i]),Double.parseDouble(propfessionWiseFees[i+1]));
}
}
else {
double feeAmount = Double.parseDouble(reqParams.get("feeAmount")[0]);
for(Profession profession: professions){
feeProfessionMap.put(Integer.valueOf(profession.getId()),feeAmount);
}
}
courseBean.setProfessionWiseFees(feeProfessionMap);
courseBean.setProfessionWiseFees(isProfessionWiseFeesApplicable);
Model class:
public class CourseBean {
// few fields
private Map<Integer, Double> professionWiseFees; // <profession_id ,fees>
// all setters and getters
}
So How can I solve this problem elegantly? requestParam.get is making the code cluttery
If you think that
use of requestParam.get reducing readability and maintainability of code.
You may use Spring web binding.
First define a FeeForm bean:
public class FeeForm {
boolean isProfessionWiseFees;
ProfessionAmount[] professionAmounts;
Double feeAmount;
}
Then define the ProfessionAmount bean:
public class ProfessionAmount {
int profession;
double amount;
}
Then change the controller method in this way:
#RequestMapping(value = { "/test.html" }, method = RequestMethod.POST)
public String testOverflow(Map<String, Object> model,
FeeForm form)
{
Map<Integer,Double> feeProfessionMap = new HashMap<>();
List<Profession> professions = (List<Profession>) servletContext.getAttribute("professionList");
if(form.isProfessionWiseFees()) {
for(ProfessionAmount f : form.getProfessionAmounts()){
feeProfessionMap.put(f.getProfession(),f.getAmount());
}
}
else {
for(Profession profession: professions){
feeProfessionMap.put(profession.getId(),form.getFeeAmount());
}
}
HTML:
<input type="radio" name="professionWiseFees" value="true"> true
<input type="radio" name="professionWiseFees" value="false"> false
<div id="totalAmount" class="hidden">
<input class="feeAmountOnly" name="feeAmount" type="text" />
</div>
<div id="professionWiseAmount" class="hidden">
<c:forEach items="${applicationScope.professionList}" var = "profession" varStatus="status" >
Course Fee For ${profession.profession}
<input type="hidden" value="${profession.id}" name="professionAmounts[${status.index}].profession" type="text"/>
<input class="feeAmoun2t" value='0' name="professionAmounts[${status.index}].fee" type="text" />
</c:forEach>
<div>
You should come to the jsp holding flag in the model bean which indicate if the fees is applicable or not based on it play on the design and disable the inapplicable options .
or
use AJAx. you can use radio button and use onchange of them to check by ajax. if it's inapplicable return validation error message.

Model Binding collections in ASP.NET MVC with hidden controls

Hihi,
Having trouble model binding with this class (the following concrete, not the abstract).
Ignore the basic properties, its the Lists that I'm interested in binding.
public abstract class MessageModel
{
public string Tag { get; set; }
public string Message { get; set; }
public int Id { get; set; }
public const int DefaultIdValue = Int32.MinValue;
public List<LinkModel> Linked { get; set; }
public List<LinkModel> NotLinked { get; set; }
protected MessageModel()
{
Id = DefaultIdValue;
Linked = new List<LinkModel>();
NotLinked = new List<LinkModel>();
}
protected MessageModel(string tag, string message):this()
{
Tag = tag;
Message = message;
}
}
public class TextModel:MessageModel
{
public int TextId { get; set; }
public TextModel()
{
TextId = DefaultIdValue;
}
}
This is the submission I get on the server side on submit (formatted for sanity):
Tag=
&Message=
&NotLinked.index=35fda83a053645e6809bbb8b0ea00103
&NotLinked.index=14c2e286e28b4c9d8f889fb3eb437e5f
&NotLinked.%5b35fda83a053645e6809bbb8b0ea00103%5d.RecipientId=1
&NotLinked.%5b35fda83a053645e6809bbb8b0ea00103%5d.RecipientName=Bob+Biggins
&NotLinked.%5b14c2e286e28b4c9d8f889fb3eb437e5f%5d.RecipientId=2
&NotLinked.%5b14c2e286e28b4c9d8f889fb3eb437e5f%5d.RecipientName=Billy+Oswold
&Submit=Submit
When the function is called that accepts that model the NotLinked collection is set to null. D:
The (relevant) output html looks like this (im trying to "faux" bind to:
<ol> and <li>
with jQuery doing the work of moving stuff around)
<div id="NotLinkedContainer">
<ol id="NotLinked" name="NotLinked" style="width: 500px;height: 200px">
<li value="1">Bob Biggins
<input id="NotLinked_index" name="NotLinked.index" type="hidden" value="a0ab331bee2a461084b686e13a87090b" />
<input id="NotLinked__a0ab331bee2a461084b686e13a87090b__RecipientId" name="NotLinked.[a0ab331bee2a461084b686e13a87090b].RecipientId" type="hidden" value="1" />
<input id="NotLinked__a0ab331bee2a461084b686e13a87090b__RecipientName" name="NotLinked.[a0ab331bee2a461084b686e13a87090b].RecipientName" type="hidden" value="Bob Biggins" />
</li>
<li value="2">Billy Oswold
<input id="NotLinked_index" name="NotLinked.index" type="hidden" value="d7d294d3174c4bd98d583e92010359e7" />
<input id="NotLinked__d7d294d3174c4bd98d583e92010359e7__RecipientId" name="NotLinked.[d7d294d3174c4bd98d583e92010359e7].RecipientId" type="hidden" value="2" />
<input id="NotLinked__d7d294d3174c4bd98d583e92010359e7__RecipientName" name="NotLinked.[d7d294d3174c4bd98d583e92010359e7].RecipientName" type="hidden" value="Billy Oswold" />
</li>
</ol>
</div>
Any ideas? Haven't done this sort of complex binding before so I'm at a loss at the simple mistake I've probably made.
Try removing the dot notation before the brackets and since this isn't a dictionary, but a list, you need to use indices, not keys. The correct syntax for a list in a razor view should look more like this:
<div id="NotLinkedContainer">
<ol id="NotLinked" name="NotLinked" style="width: 500px;height: 200px">
<li value="1">Bob Biggins
<input id="NotLinked_index" name="NotLinked.index" type="hidden" value="a0ab331bee2a461084b686e13a87090b" />
<input id="NotLinked__a0ab331bee2a461084b686e13a87090b__RecipientId" name="NotLinked[0].RecipientId" type="hidden" value="1" />
<input id="NotLinked__a0ab331bee2a461084b686e13a87090b__RecipientName" name="NotLinked[0].RecipientName" type="hidden" value="Bob Biggins" />
</li>
<li value="2">Billy Oswold
<input id="NotLinked_index" name="NotLinked.index" type="hidden" value="d7d294d3174c4bd98d583e92010359e7" />
<input id="NotLinked__d7d294d3174c4bd98d583e92010359e7__RecipientId" name="NotLinked[1].RecipientId" type="hidden" value="2" />
<input id="NotLinked__d7d294d3174c4bd98d583e92010359e7__RecipientName" name="NotLinked[1].RecipientName" type="hidden" value="Billy Oswold" />
</li>
</ol>
</div>
Here is an article that covers what you are attempting to do:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Unobtrusive validation editorfor

I've got a partial View, loaded from an Action, so the parent view contains:
#Html.Action("TourSearch")
The TourSearch View uses a editor as such:
#Html.EditorFor(model => model.ImpersonatedAgentModel, "ImpersonatedAgentView")
where ImpersonatedAgentModel is as such:
[Serializable]
public class ImpersonatedAgentModel
{
[Required(ErrorMessage = "Please provide a User ref")]
public string AgentImpersonatedUserName { get; set; }
[Required(ErrorMessage="Please provide a ABTA/AgencyCode")]
public string AgentImpersonatedBranchCode { get; set; }
[Required(ErrorMessage = "Please provide a User ref")]
public int? AgentImpersonatedBranchID { get; set; }
}
My editor is pretty straight forward:
#model Travel2.WebUI.Models.ImpersonatedAgentModel
<ul id="agencyDetails">
<li>
<label for="AgentImpersonatedBranchCode">ABTA/Agency Code: *</label>
#Html.TextBoxFor(model => model.AgentImpersonatedBranchCode, new {ID="txtBranchCode" })
#Html.ValidationMessageFor(model => model.AgentImpersonatedBranchCode, "*")
<input id="txtBranchId", type="hidden" value="#Model.AgentImpersonatedBranchID" />
<input id="txtUserName", type="hidden" value="#Model.AgentImpersonatedUserName" />
<input id="hidCurrentController" type="hidden" value='#ViewContext.Controller.ValueProvider.GetValue("controller").RawValue' />
</li>
<li>
<label for="AgentImpersonatedUserName">User ref: *</label>
<select id="ddlUser" disabled="disabled" ></select>
<input type="hidden" id="txtUserID" />
#Html.HiddenFor(model => model.AgentImpersonatedUserName, new {ID="AgentImpersonatedUserName" })
#Html.HiddenFor(model => model.AgentImpersonatedBranchID, new {ID="AgentImpersonatedBranchID"})
#Html.ValidationMessageFor(model => model.AgentImpersonatedUserName, "*")
</li>
</ul>
Now in Chrome, all works fine. But when I fill in the form in IE but not the data in the Editor, it passes validation incorrectly!
If I examine the markup, using IEs poor excuse for Firebug, I can see the validation attributes,
<input name="ImpersonatedAgentModel.AgentImpersonatedBranchCode" id="txtBranchCode" type="text" data-val="true" data-val-required="Please provide a ABTA/AgencyCode" jQuery172048066185567747205="94"/>
so why is IE ignoring them!! Stupid IE
Found the answer here:
http://www.tigraine.at/2011/08/26/jquery-validate-and-microsofts-unobtrusive-validation-dont-play-well-together/
We were referencing Jquery validation too and this seems to be causing this error

How to submit values from a view?

Hi all I have a view with these controls on it
<input type="text" class="radius2" />
<input type="button" value="Place bid" class="bid-btn" />
I want to pass the value in the text box to another view (via an action method) when the button is clicked. The action method should render the view.
How can this be acheived?
Thanks,
Sachin
#using(Html.BeginForm("SubmitAction", "Home", FormMethod.Post))
{
<input id="radius2" name="radius2" type="text" class="radius2" />
<input type="submit" value="Place bid" class="bid-btn" />
}
[HttpPost]
public ActionResult SubmitAction(string radius2)
{
return AnotherView(radius2);
}
public ActionResult AnotherView(string value)
{
return View();
}
Written in notepad so might require small syntax changes
add name property to the tags so the server can access them
<input name="Name1" type="text" class="radius2" />
<input type="button" value="Place bid" class="bid-btn" />
then when submit your action should be something like this
public ActionResult SubmitAction(string name1)
{
return View("ViewName" , /* the model here */ )
}

MVC3 - Understanding POST with a button

How does one obtain the form data after submitting it?
<form target="_self" runat="server">
<p>
<select id="BLAHBLAH2">
<option>2010</option>
<option>2011</option>
<option>2012</option>
<option>2013</option>
</select>
<input type="submit" runat="server" value="Change Year" />
</p>
</form>
This hits the controller's Index method. But, there's nothing in Request.Form. Why?
Second, can I use
<input type="button" instead of type=submit? That is, without introducing ajax via onclick.
Finally, how do I submit to a different method in the controller, e.g. Create?
Try removing those runat server tags. They should not be used in ASP.NET MVC. Also your select doesn't have a name. If an input element doesn't have a name it won't submit anything. Also your option tags must have value attributes which indicates what value will be sent to the server if this options is selected:
<form action="/Home/Create" method="post">
<p>
<select id="BLAHBLAH2" name="BLAHBLAH2">
<option value="2010">2010</option>
<option value="2011">2011</option>
<option value="2012">2012</option>
<option value="2013">2013</option>
</select>
<input type="submit" value="Change Year" />
</p>
</form>
But the correct way to generate forms in ASP.NET MVC is to use HTML helpers. Depending on the view engine you are using the syntax might be different. Here's an example with the Razor view engine:
#model MyViewModel
#using (Html.BeginForm("Create", "Home"))
{
<p>
#Html.DropDownListFor(x => x.SelectedYear, Model.Years)
<input type="submit" value="Change Year" />
</p>
}
Here you have a strongly typed view to some given view model:
public class MyViewModel
{
public string SelectedYear { get; set; }
public IEnumerable<SelectListItem> Years
{
get
{
return Enumerable
.Range(2010, 4)
.Select(x => new SelectListItem
{
Value = x.ToString(),
Text = x.ToString()
});
}
}
}
which is populated by some controller action that will render this view:
public class HomeController: Controller
{
public ActionResult Index()
{
var model = new MyViewModel();
return View(model);
}
[HttpPost]
public ActionResult Create(MyViewModel model)
{
... model.SelectedYear will contain the selected year
}
}
None of your <option> tags have a value:
...
<option value="2010">2010</option>
...
As noted by David, runat="server" is most definitely a WebForms thing, so you can 86 that.
If you want to submit to a different method on your controller you just need to specify the URL for that method.
Easy way using Html.BeginForm:
#using (Html.BeginForm("AnotherAction", "ControllerName")) {
<!-- Your magic form here -->
}
Using Url.Action
<form action="#Url.Action("AnotherAction")" method="POST">
<!-- Your magic form here -->
</form>
You can also use
In Controller
int Value = Convert.ToInt32(Request["BLAHBLAH2"]); //To retrieve this int value
In .cshtml file use
<select id="IDxxx" name="BLAHBLAH2">
//Request[""] will retrieve the VALUE for the html object ,whose "name" you request.

Resources