I have an ICollection<String> being passed to my view and I do a foreach to load a partial view. It loops through the correct number of times, however, the value it passes is the same and I know in the model that this is not the case.
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View("Index", new List<String>());
}
[HttpPost]
public ActionResult Index(List<String> txtValue)
{
return View("Index", txtValue);
}
}
View:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<List<String>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Home
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<script type="text/javascript">
//Deletes the div the Control is in.
$(".delete").live("click", function () {
$(this).parent().remove();
});
//Adds the TextBoxes to divControls
function AddTextBox(Value) {
var elements = "<div><input name=\"txtValue\" type=\"text\" /><input type=\"button\" class=\"delete\" value=\"-\" /><br/></div>";
$("#divControls").append(elements);
}
</script>
<h2>Controls!!!</h2>
<input id="btnAdd" type="button" name="Refresh" value="+" onclick="AddTextBox()" />
<% using (Html.BeginForm())
{ %>
<input id="btnsubmit" type="submit" name="Submit" onclick="Submit" />
<div id="divControls">
<%
foreach (var text in this.Model)
{ %>
<%=Html.TextBox("txtValue", text, new { id = "Value", name = "txtValue" })%>
<% Html.RenderPartial("TextControl", text);
}
%>
</div>
<%
}
%>
</asp:Content>
TextControl.ascx
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<String>" %>
<div>
<%=Html.TextBox("txtValue", this.Model, new { id = "Value", name = "txtValue" }) %>
<input id="btn" type="button" class="delete" value="-" /><br/>
</div>
The values of the model passed from the controller to the view are correct, even when passed to the user control "TextControl" the value is correct, but when the Textbox displays they are all just the first value of the original model passed in.
Ex.
Model as List<String> { "1", "2", "3", "4" }
passed to the view, will iterate through each one correctly, passing the correct string to "TextControl" to create a Html.TextBox("name", this.Model). Everything on the debugging side appears correct, however, when it finishes all the textboxes are "1" (or the first value in the list).
Here's a link to my exact code: http://www.sendspace.com/file/sypl1u
Note:
I came up with a solution of just using <input type="text" name="txtValue" value="<%= this.Model %>" /> instead.
Potential issue: you are using ElementAt which is LINQ method that fave special behavior for IList argument, but you are passing in txtValue as result of some query. In this case ElementAt may case sequence to be enumerated multiple times and may even fail if sequence can't be re-enumerated.
Consider simple foreach on the collection instead:
foreach (var text in Model)
{
Html.RenderPartial("TextControl", text);
}
Related
I am working on SharePoint to create a Feedback questionnaire form using an application page that is basically a aspx page.
I wish to do this by emulating MVC as far as possible. I've set up my model in the code-behind:
public List<QuestionViewModel> modelQuestions = new List<QuestionViewModel>();
Next, I need to display each question and an appropriate input depending on the question type (e.g. single line, multi line, single selection, multiple selection).
I've got it displaying the questions correctly:
<fieldset class="what-went-wrong">
<% for (int i = 0; i < modelQuestions.Count; i++) { %>
<p>
<label for="QuestionText">
<% if (modelQuestions[i].Required) { %>
<span class="req-field indicator">*</span>
<% } %>
<%= modelQuestions[i].QuestionText %>
<% if (modelQuestions[i].Required) { %>
<span class="req-field right">* Required field</span>
<% } %>
</label>
</p>
<% } %>
</fieldset>
This give's me the question text. I'm now trying to construct the appropriate input, but this <% %> tags is not working for this:
<% if(modelQuestions[i].QuestionTypeId == QuestionType.SingleLine) { %>
<input id="modelQuestions_<% i %>" name="modelQuestions[<% i %>]" type="text" placeholder="<% modelQuestions[i].Placeholder %>" />
<% } %>
I can't seem to get it to construct the html element using details from the model (in the value for id, name, placeholder etc.)
Also, I've no idea how to go about posting this back to the server when I get to that point.
Is there any merit in continuing? Are there other controls/methods more appropriate to use in this case with aspx?
You cannot generate HTML markup like this. Even data-binding expressions will not help, because they bind ASP.NET controls' attributes values, not the plain output HTML in the page.
You should generate the markup in the "code behind", like this:
Page markup:
<div id='AnswersPanel'>
<div>
Page code behind:
protected void PageLoad(...)
{
AnswersPanel.InnerHtml = "";
AnswersPanel.InnerHtml += string.Format("<input id='modelQuestions_{0}' name='modelQuestions[{0}]' type='text' placeholder='{1}' />",
i.ToString(),
modelQuestions[i].Placeholder);
}
I have a SearchController.cs in my controller folder, it has an Action named Index. My search folder has a view named Index
The following code is in my /Controller/SearchController
private TEAM2BooksDBEntities _db = new TEAM2BooksDBEntities();
[HttpPost]
public ActionResult Index(string SearchFor)
{
var query = _db.Books.Where(em => em.title.Contains(SearchFor)).ToList();
return View(query);
}
The following code is in my /Home/Index
<% using(Html.BeginForm("Index","Search")){ %>
<%= Html.TextBox("SearchFor") %>
<input type="submit" value="Submit" />
<% }%>
But no matter what I do when I hit the submit button it just reloads the current page. I want it to send the contents of the "SearchFor" box as a parameter to the Index action in the Search controller. How can I fix this?
I also suggest try to use this.
<% using(Html.BeginForm("Index","Search",FormMethod.Post)){ %>
<%= Html.TextBox("SearchFor") %>
<input type="submit" value="Submit" />
<% }%>
Try this inside your action :
string SearchFor= Request.Form["SearchFor"];
I have the following View. This is the whole code of my view
<asp:Content ID="Content2" ContentPlaceHolderID="HeadContent" runat="server">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<div>
<table>
<tr>
<td>
<select id="clientDDL">
</select>
<% Html.DropDownList("clientDDL",
new SelectList((IEnumerable)ViewData["Clients"], "Code", "Name")); %>
</td>
</tr>
</table>
</div>
</asp:Content>
I use the next ViewData from my Model:
public static List<lookup> GetClients()
{
using (ModelDataContext data = new ModelDataContext(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
List<lookup> retVal = new List<lookup>();
List<Client> lClient = data.Clients.Where(a => a.IsActive == true).ToList();
lClient = lClient.OrderBy(o => o.ClientName).ToList();
foreach (Client item in lClient)
{
retVal.Add(new lookup() { Code = item.ClientID.ToString(), Name = item.ClientName, });
}
return retVal;
}
}
This is my Controller:
public ActionResult ProcedureFilter()
{
ViewData["Clients"] = WorkflowModels.GetClients();
return View();
}
What did I miss? My DropDownList is still empty. Maybe i have to put some reference? Any suggestions please.
UPDATE:
The problem was ';' at the end of part <%= %>. The works code:
<%= Html.DropDownList("clientDDL",
new SelectList((IEnumerable)ViewData["Clients"], "Code", "Name")) %>
In the ASP.NET code you provided, 2 HTML select tags (or DropdownLists) are defined with the same id (cliendDDL) :
<select id="clientDDL"> <-- the first one
</select>
<% Html.DropDownList("clientDDL",
new SelectList((IEnumerable)ViewData["Clients"], "Code", "Name")); %> <-- the second one, Html.DropDownList generating a select under the hood.
Would it be possible that only the first one is displayed (the empty one) and the second remains hidden because of a missing character, changing your expected HTML generation routine (Html.DropDownList) into an Embedded Code Block?
Maybe instead of :
<% Html.DropDownList
it should be :
<%= Html.DropDownList or <%: Html.DropDownList
See here for <%:%> ASP.NET 4 syntax
Edited
Also the ";" end of line character is not needed and should be removed.
View Page:
"<%=Html.DropDownList("Description", New SelectList(ViewData("Description")), "--Select--")%>"
Contoller:
Function Purchase() As ActionResult:
Dim dataContext As New tblMVCDataContext
Dim teststr As String
Dim itemVar = From U In dataContext.Items Select U.Description
For Each tbItem In itemVar
teststr += tbItem + ","
Next
ViewData("Description") = teststr.Split(",")
Return View(itemVar)
End Function
I'm new in MVC2, so sorry for stupid question. I looked for nice answer, but can't find it. So my question is:
I have view:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MyProject.MyDB.MyProducts>>" %>
<%# Import Namespace="MyProject.MyDB" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Content" runat="server">
<% using (Html.BeginForm())
{%>
<table>
<%
foreach (var item in Model)
{%>
<tr>
<td>
<%:item.name%>
</td>
<td>
<%:String.Format("{0:g}", item.date)%>
</td>
</tr>
<% } %>
</table>
<div>
<%:Html.TextArea("MyTextArea")%>
</div>
<p>
<input type="submit" value="Send" />
</p>
<% } %>
</asp:Content>
My controller is:
[HttpGet]
public ActionResult ViewMyProducts(int id)
{
List<MyProducts> myModel = GetMyProducts(id);
return View(myModel);
}
[HttpPost]
public ActionResult ViewMyProducts(/*???What should I put here???*/)
{
if(/*I want "MyTextArea" value here*/ == something && myModel/*from view*/.count==5}
{
//do something
}
return View(myModel);
}
So, in HttpPost I need myModel from view and value of "MyTextArea" from view. How can I get them?? I'll appreciate any help.
I would think that the following should work:
[HttpPost]
public ActionResult ViewMyProducts(string MyTextArea)
A helpful thing to do would be to explicitly call your Action in your Form - by changing this line:
<% using (Html.BeginForm())
to
<% using (Html.BeginForm("ViewMyProducts","ControllerName",HttpMethod.Post))
to ensure that the Submit action redirects it to the right Action.
As far as the model is concerned:
If you are just checking the Count - you could make a hidden field that returns the number of items in the "Model" like such:
<%: Html.Hidden("modelCount", Model.Count());
but if you want the entire Model - it would be need to be something like this:
<%: Html.Hidden("myModel", Model);
then you could further modify your Action to look something like this:
ViewMyProducts(string MyTextArea, int modelCount)
{
//...
}
or
ViewMyProducts(string MyTextArea, IEnumerable<MyProject.MyDB.MyProducts> myModel)
{
//...
}
Although you have access inside of the Controller to refresh the Model - so if you didn't need to pass back the entire thing you could still repopulate your view with a fresh call.
string myTextArea - or you could just check the FormCollection (I would recommend the named variable).
If you want to get the model back from the view, you will need to serialize it out as well in order to get back the values. If this is the case, I would convert the whole thing to a view model that either derives from your Model or has a public property that is your model, add a property for MyTextArea and then emit hidden input's for you model, named for the appropriate properties. Assuming that your model is persisted somewhere (database), I would just pass the key (id) and rehydrate the object from within the action result.
[HttpPost]
public ActionResult ViewMyProducts(ViewMyProductsViewModel viewModel)
{
if(viewModel.MyTextArea == "something" && (IEnumerable<foo>)myModel).Count()==5)) {
var model = repo.Get(myModel.First().Id);
// do something with the model
}
return View(viewModel);
}
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MyProject.MyDB.MyProducts>>" %>
<%# Import Namespace="MyProject.MyDB" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Content" runat="server">
<% using (Html.BeginForm())
{%>
<table>
<%
foreach (var item in Model)
{%>
<tr>
<td>
<input type="hidden" name="viewModel.Id" value="<%:item.id%>" />
<%:item.name%>
</td>
<td>
<%:String.Format("{0:g}", item.date)%>
</td>
</tr>
<% } %>
</table>
<div>
<%:Html.TextArea("MyTextArea")%>
</div>
<p>
<input type="submit" value="Send" />
</p>
<% } %>
</asp:Content>
First of all You are rendering item.name and item.date as a text not html control. So You won't be able to receive it in controller method parameters.
For some reason the paramater OriginalLocation is always null in the following code. What am I doing wrong?
Controller:
[HttpPost]
public ActionResult File(HttpPostedFileBase OriginalLocation, FileModel model)
{
byte[] binaryData = null;
if (OriginalLocation != null && OriginalLocation.ContentLength > 0)
{
binaryData = new byte[OriginalLocation.ContentLength];
OriginalLocation.InputStream.Read(binaryData, 0,
OriginalLocation.ContentLength);
if (model.UploadFile(OriginalLocation))
{
return RedirectToAction("Profile", "Account");
}
}
return View();
}
View:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MasterPage.Master" Inherits="System.Web.Mvc.ViewPage<NISE.Web.TestForum.Models.File.FileModel>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="head" runat="server">
Find upload
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContentPlaceHolder" runat="server">
<% using (Html.BeginForm("File", "File", FormMethod.Post, new { enctype = "multipart/form-data" }))
{ %>
<%--<form enctype="multipart/form-data" method="post" action="/File/File">--%>
<input type="file" name="OriginalLocation" id="OriginalLocation" />
<input type="submit" value="Upload" />
<%--</form>--%>
<%} %>
</asp:Content>
Model:
public bool UploadFile(HttpPostedFileBase OriginalLocation)
{
if (OriginalLocation != null)
{
var filename = Path.GetFileName(OriginalLocation.FileName);
OriginalLocation.SaveAs(#"C:\" + filename);
return true;
}
return false;
}
I think you just need to remove the FileModel model parameter from your Action method. Nothing is being passed to it, and so it's screwing up model binding (unless there is more code in the view that you have deleted from your post).