append two IEnumerable items - asp.net-mvc-3

IEnumerable<Addresses> AddressSet1=myServices.GetAddresses(LocationId1);
IEnumerable<Addresses> AddressSet2=myServices.GetAddresses(LocationId2);
I want to combine the above two AddressSets
I tried IEnumerable<Addresses> AllAddresses=AddressSet1.Concat(AddressSet2)
But after this when I try to access items from IEnumerable AllAddresses by on my razor view
#if(!myHelper.IsNullorEmpty(model.AllAddresses )
{
#Html.EditorFor(model => model.AllAddresses )
}
and I am getting errors -- Illegal characters in path .Any suggestions to identify cause of this error ?
If I am trying to run my page with out the Concat I am able see the records in AddressSet1 /AddressSet2 displayed on the page .But when I try to combine the two to form I Enumerable AllAddresses ,it is throwing errors please help
pasted below is my Editor Template
#model MyServiceRole.Models.Addresses
#{
ViewBag.Title = "All addresses Items";
}
<table>
<tr>
<td>
<span>Index</span>
</td>
<td>
</tr>
<tr>
<td>Address XID</td>
<td>
#Html.EditorFor(model => model.AddressID)
</td>
</tr>
<tr>
<td>Title</td>
<td>
#Html.EditorFor(model => model.Title)
</td>
</tr>
<tr>
<td>Description</td>
<td>
#Html.EditorFor(model => model.Description)
</td>
</tr>
<tr>
<td>Image URL</td>
<td>
#Html.EditorFor(model => model.Photo.URL)
</td>
</tr>
</table>

I tested your issue and ran into the same problem.
List<string> a = new List<string>{ "a" };
List<string> b = new List<string>{ "b" };
IEnumerable<string> concat = a.Concat<string>(b);
foreach(string s in concat) { } // this works
return View(concat);
In view:
#model IEnumerable<string>
#foreach(string s in Model) //This blows up
{
}
#Html.EditorFor(m => Model) //Also blows up
It looks like you honestly can't use templates with or enumerate over the
System.Linq.Enumerable.ConcatIterator<T>
class that Concat creates within a View. This seems like a bug.
Anyway adding .ToList() fixes your issue.
return View(concat.ToList());

If you want to use editor templates why are you writing foreach loops? You don't need this loop at all. Simply write the following and get rid of the foreach:
#Html.EditorFor(x => x.AllAddresses)
and then you will obviously have a corresponding editor template that ASP.NET MVC will automatically render for each element of the AllAddresses collection so that you don't need to write any foreach loops in your view (~/Views/Shared/EditorTemplates/Address.cshtml):
#model Address
...

Related

When using AjaxHelper to retrieve a partial view, the embedded data is always the same

We use ASP.NET MVC 5's AjaxHelper and Ajax.BeginForm to request a partial view. That request also needs some JSON data in order to update a map control.
The view rendering part of the process works great (a table body is replaced with the strongly-typed partial view), but the JSON data (embedded into the data-json attribute of the div element as described in this answer and retrieved in my OnSuccess function) always has the same value.
To eliminate the controller code or ViewBag as culprit, I replaced the JSON data (originally retrieved from the ViewBag) with a direct call to DateTime.Now. Sure enough, the same DateTime is printed each time in updateMap() (e.g., 2/11/2016+5:24:42+PM)
I've tried disabling caching, and changing the HTML method to Post, in my AjaxOptions.
In the Parent View (changing the ListBox selection submits the form):
#model string
#{
ViewBag.Title = "Project List";
AjaxOptions ajaxOpts = new AjaxOptions
{
UpdateTargetId = "tableBody",
OnSuccess = "updateMap",
HttpMethod = "Post",
AllowCache = false
};
}
#using (Ajax.BeginForm("GetProjectsData", ajaxOpts))
{
<fieldset>
<legend>Project State</legend>
<div class="editor-field">
#Html.ListBox("selectedStates", ViewBag.StatesList as MultiSelectList,
new { #class = "chzn-select", data_placeholder = "Choose States...", style = "width:350px;", onchange = "$(this.form).submit();" })
</div>
</fieldset>
}
<table class="table">
<thead>
<tr>
<th>
Project Name
</th>
<th>
Project Firm
</th>
<th>
Project Location
</th>
<th>
Building Type
</th>
<th>
Project Budget
</th>
<th></th>
</tr>
</thead>
<tbody id="tableBody">
#Html.Action("GetProjectsData", new { selectedStates = Model })
</tbody>
</table>
<script>
function updateMap() {
var jsonData = $("#geoJsonData").attr("data-json");
var decoded = decodeURIComponent(jsonData);
console.log(decoded); // always prints same value
}
</script>
The partial view:
#model IEnumerable<OurModel>
<div id="geoJsonData" data-json="#Url.Encode(DateTime.Now.ToString())"></div>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.NAME)
</td>
<td>
#Html.DisplayFor(modelItem => item.COMPANY_NAME)
</td>
<td>
#Html.DisplayFor(modelItem => item.STATE)
</td>
<td>
#Html.DisplayFor(modelItem => item.BUILDING_TYPE)
</td>
<td>
#Html.DisplayFor(modelItem => item.BUDGET_AMT)
</td>
</tr>
}
I'm hesitant to jettison the MVC helper classes' pattern of returning a partial view and instead manually render a view into a JSON object. Why is the updated tablebody visible on screen, but when jQuery requests the div element it always has the same data?
Interesting...replacing the div with a good old hidden input element worked. Now fresh data is retrieved each time.
This
<div id="geoJsonData" data-json="#Url.Encode(DateTime.Now.ToString())"></div>
Became this
<input id="geoJsonData" type="hidden" value="#Url.Encode(DateTime.Now.ToString())" />
I wonder why the data-json in the div remained "stale" while the value of the input field did the trick?

MVC 3 Processing a table row depending on whether a check box is checked

Hi I am very new to MVC and I am currently trying to implement a small human resources system using MVC 3 and Entity Framework 4.1. Right now I am stuck on what seems like a very trivial task of displaying a table which lists employees who have recently taken sick leave off from work and on each table row I have a checkbox which users will check if the the employee has provided a sick sheet. I also want to have a button/Link/etc on each row which when clicked would invoke a call to a controller method and somehow pass the checked value of the check box together with the id of the sick leave application. I tried using an actionlink but I'm kind of stumped at what I would enter in as the routevalue meant for the checked value of the checkbox. This same functionality would take me only minutes to do in web forms but like I said I'm new to MVC and since this seems like a pretty simple task there is probably a pretty simple solution somewhere out there but I just can't figure it out for the life of me. If anything I'm guessing this might need a bit of jquery (which btw still looks like a foreign language to me sometimes) and hidden fields? Arrgghhh I don't know. Could someone please help me?? Thanks in advance.
Here is my View:
#model IEnumerable<LeaveSoft.Models.PendingSickLeave>
<table>
<tr>
<th>
Applicant's Name
</th>
<th>
Leave Start
</th>
<th>
Leave End
</th>
<th>
Number Of Days
</th>
<th>
Reason
</th>
<th>
Confirm
</th>
<th>
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserFullName)
</td>
<td>
#Html.DisplayFor(modelItem => item.StartDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.EndDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.NumOfDays)
</td>
<td>
#Html.DisplayFor(modelItem => item.LeaveReason)
</td>
<td>
#Html.CheckBox("chkConfirm")
#Html.Label("", "Sick Sheet Provided")
</td>
<td>
#Html.ActionLink("Process", "ProcessSickLeave", new { id = item.ApplicationID, sicksheet = "THIS IS THE PART I DON'T KNOW" })
</td>
</tr>
}
</table>
here's a quick solution off the top of my head (table shortened due to my laziness):
HTML/RAZOR:
<table>
<tr>
<th>ApplicantName</th>
<th>Confirm</th>
<th></th>
</tr>
#foreach (var item in Model.PendingSickLeave) // this is a List<>
{
<tr>
<td>#item.UserFullName</td>
<td>#Html.CheckBoxFor(m => item.SickSheet, new { #id = "chk" + #item.ApplicationID })</td>
<td>#Html.ActionLink("Process", "ProcessSickLeave", new { id = item.ApplicationID }, new { #class="submit", #data_val = item.ApplicationID })</td>
</tr>
}
</table>
JQUERY SCRIPT:
<script>
$(function () {
// captures click event. appends the sicksheet querystring on the url.
$('a.submit').click(function (e) {
e.preventDefault();
var id = $(this).attr('data-val');
var chk = $('#chk' + id);
if ($(chk).is(':checked'))
$(this).attr('href', $(this).attr('href') + '?sicksheet=true');
else
$(this).attr('href', $(this).attr('href') + '?sicksheet=false');
});
});
</script>
Basically, when you click on the Process actionlink, the jquery looks for a checkbox with matching ID, then if it's checked, it puts a ?sicksheet=true at the end of the url before continuing.
edit:
ROUTE:
routes.MapRoute("ProcessSickLeave", "process/processsickleave/{applicationid}",
new { controller = "Process", action = "ProcessSickLeave" });
CONTROLLER:
public ActionResult ProcessSickLeave(ProcessViewModel m)
{
return Content("ID = " + m.ApplicationID +
"<br/> Has Sick sheet: " + m.SickSheet.ToString(), "text/html");
}

MVC3 radiobuttons do not behave like they should

I have a problem that's starting to drive me crazy.. I've narrowed my problem down to the following test case:
Model:
public class TestModel
{
public bool TestBool { get; set; }
}
Index View:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.Action("Test")
Test View:
#model IEnumerable<Test_GUI.Models.TestModel>
#using (Html.BeginForm()) {
<table>
#Html.EditorForModel()
</table>
<input type="submit" value="OK"/>
}
Editor template;
<tr>
<td>
Yes
#Html.RadioButtonFor(m => m.TestBool, Model.TestBool)
</td>
<td>
No
#Html.RadioButtonFor(m => m.TestBool, !Model.TestBool)
</td>
In the TestController, I create two instances of TestModel with a value of false and pass them to the view. But the radiobuttons are rendered as checked, and they also return as true if I post the form..
I've tried many other ways to display the radiobuttons, but nothing seems to work. This seems like to correct way to do it.
I must be able use the current value of the boolean, so I cannot use fixed true or false values in the view. If I do use a fixed true/false, I do get the correct values on the form and in the controller after posting the form..
Try like this:
<td>
Yes
#Html.RadioButtonFor(m => m.TestBool, true)
</td>
<td>
No
#Html.RadioButtonFor(m => m.TestBool, false)
</td>

Use Html.RadioButtonFor and Html.LabelFor for the same Model but different values

I have this Razor Template
<table>
<tr>
<td>#Html.RadioButtonFor(i => i.Value, "1")</td>
<td>#Html.LabelFor(i => i.Value, "true")</td>
</tr>
<tr>
<td>#Html.RadioButtonFor(i => i.Value, "0")</td>
<td>#Html.LabelFor(i => i.Value, "false")</td>
</tr>
</table>
That gives me this HTML
<table>
<tr>
<td><input id="Items_1__Value" name="Items[1].Value" type="radio" value="1" /></td>
<td><label for="Items_1__Value">true</label></td>
</tr>
<tr>
<td><input checked="checked" id="Items_1__Value" name="Items[1].Value" type="radio" value="0" /></td>
<td><label for="Items_1__Value">false</label></td>
</tr>
</table>
So I have the ID Items_1__Value twice which is - of course - not good and does not work in a browser when I click on the second label "false" the first radio will be activated.
I know I could add an own Id at RadioButtonFor and refer to that with my label, but that's not pretty good, is it? Especially because I'm in a loop and cannot just use the name "value" with an added number, that would be end up in multiple Dom Ids in my final HTML markup as well.
Shouldn't be a good solution for this?
Don't over-engineer a solution for this. All you are trying to accomplish is to have the radio buttons respond to clicks on the text. Keep it simple and just wrap your radio buttons in label tags:
<table>
<tr>
<td><label>#Html.RadioButtonFor(i => i.Value, "1")True</label></td>
</tr>
<tr>
<td><label>#Html.RadioButtonFor(i => i.Value, "0")False</label></td>
</tr>
</table>
The LabelFor html helper is usually used to bring in the Name from the Display attribute on your View Model (e.g. "[Display(Name = "Enter your Name")]).
With radio buttons, the name isn't particularly useful, because you have a different line of text for each radio button, meaning you are stuck hard coding the text into your view anyway.
I've been wondering how MVC determines "nested" field names and IDs. It took a bit of research into the MVC source code to figure out, but I think I have a good solution for you.
How EditorTemplates and DisplayTemplates determine field names and IDs
With the introduction of EditorTemplates and DisplayTemplates, the MVC framework added ViewData.TemplateInfo that contains, among other things, the current "field prefix", such as "Items[1].". Nested templates use this to create unique names and IDs.
Create our own unique IDs:
The TemplateInfo class contains an interesting method, GetFullHtmlFieldId. We can use this to create our own unique IDs like so:
#{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("fieldName");}
#* This will result in something like "Items_1__fieldName" *#
For The Win
Here's how to achieve the correct behavior for your example:
<table>
<tr>
#{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioTrue");}
<td>#Html.RadioButtonFor(i => i.Value, "1", new{id})</td>
<td>#Html.LabelFor(i => i.Value, "true", new{#for=id})</td>
</tr>
<tr>
#{id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioFalse");}
<td>#Html.RadioButtonFor(i => i.Value, "0", new{id})</td>
<td>#Html.LabelFor(i => i.Value, "false", new{#for=id})</td>
</tr>
</table>
Which will give you the following HTML:
<table>
<tr>
<td><input id="Items_1__radioTrue" name="Items[1].Value" type="radio" value="1" /></td>
<td><label for="Items_1__radioTrue">true</label></td>
</tr>
<tr>
<td><input checked="checked" id="Items_1__radioFalse" name="Items[1].Value" type="radio" value="0" /></td>
<td><label for="Items_1__radioFalse">false</label></td>
</tr>
</table>
Disclaimer
My Razor syntax is underdeveloped, so please let me know if this code has syntax errors.
For what its worth
It's pretty unfortunate that this functionality isn't built-in to RadioButtonFor. It seems logical that all rendered Radio Buttons should have an ID that is a combination of its name AND value, but that's not the case -- maybe because that would be different from all other Html helpers.
Creating your own extension methods for this functionality seems like a logical choice, too. However, it might get tricky using the "expression syntax" ... so I'd recommend overloading .RadioButton(name, value, ...) instead of RadioButtonFor(expression, ...). And you might want an overload for .Label(name, value) too.
I hope that all made sense, because there's a lot of "fill in the blanks" in that paragraph.
#Scott Rippey nearly has it, but i guess he must be using a different version of MVC3 to me because for me #Html.LabelFor has no overloads that will take 3 arguments. I found that using the normal #Html.Label works just fine:
#{string id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioButton_True");}
#Html.Label(id, "True:")
#Html.RadioButtonFor(m => m.radioButton, true, new { id })
#{id = ViewData.TemplateInfo.GetFullHtmlFieldId("radioButton_False");}
#Html.Label(id, "False:")
#Html.RadioButtonFor(m => m.radioButton, false, new { id })
this allows you to click on the label and select the associated radiobutton as you'd expect.
Here's an HtmlHelper you can use, though you may with to customize it. Only barely tested, so YMMV.
public static MvcHtmlString RadioButtonWithLabelFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes = null)
{
var name = ExpressionHelper.GetExpressionText(expression);
var id = helper.ViewData.TemplateInfo.GetFullHtmlFieldId(name + "_" + value);
var viewData = new ViewDataDictionary(helper.ViewData) {{"id", id}};
if (htmlAttributes != null)
{
var viewDataDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
foreach (var keyValuePair in viewDataDictionary)
{
viewData[keyValuePair.Key] = keyValuePair.Value;
}
}
var radioButton = helper.RadioButtonFor(expression, value, viewData);
var tagBuilder = new TagBuilder("label");
tagBuilder.MergeAttribute("for", id);
tagBuilder.InnerHtml = value.ToString();
return new MvcHtmlString(radioButton.ToHtmlString() + tagBuilder.ToString());
}
Not Perfect but work though,
<table>
<tr>
<td>#ReplaceName(Html.RadioButtonFor(i => i.Value, "1"))</td>
<td>#Html.LabelFor(i => i.Value[0], "true")</td>
</tr>
<tr>
<td>#ReplaceName(Html.RadioButtonFor(i => i.Value, "0"))</td>
<td>#Html.LabelFor(i => i.Value[1], "false")</td>
</tr>
</table>
#functions {
int counter = 0;
MvcHtmlString ReplaceName(MvcHtmlString html){
return MvcHtmlString.Create(html.ToString().Replace("__Value", "__Value_" + counter++ +"_"));
}
}
You can add text with tags
<td>#Html.RadioButtonFor(i => i.Value, true) <text>True</text></td>
<td>#Html.RadioButtonFor(i => i.Value, false) <text>False</text></td>
Apparently there is a good solution
<td>#Html.RadioButtonFor(i => i.Value, true)</td>
<td>#Html.RadioButtonFor(i => i.Value, false)</td>

MVC Razor Rendering controls dynamically

This is one way I've found to render controls dynamically with ASP.NET MVC 3 Razor. This is giving me correct data, but I'm curious if anyone sees any red flags with this method, or a painfully more obvious way to do this.
#using (Html.BeginForm())
{
foreach (var item in Model)
{
<tr>
<td>
#item.app_name
</td>
<td>
#item.setting_name
</td>
<td>
#item.setting_description
</td>
<td>
#if (item.data_type == "Bit")
{
#Html.CheckBox("setting_value", item.setting_value == "1" ? true : false)
}
else
{
#Html.TextBox("setting_value", item.setting_value)
}
</td>
<td>
#item.setting_value
</td>
</tr>
}
}
You could use Editor and Display Templates instead...
Check out this link:
http://blogs.msdn.com/b/nunos/archive/2010/02/08/quick-tips-about-asp-net-mvc-editor-templates.aspx
What do editor templates have to do with dynamically creating controls?
What if you need to drive a UI/View from settings in a database, for example?

Resources