im new in MVC 1.
In my project im assigning IList to model and using forloop im assigning to Textbox , dropdox etc... User can change the value as per there requirement. What i want, how i will get the value present on aspx page in the form of ILIST when user click on SAVE ALL button present at the top of the page.
here are the code which im using for populating form....
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm("MyController", "EditCopyRestaurantMealRate", FormMethod.Post, new { id = "frmEditCopyRestaurantMealRate" }))
{ %>
<%= Html.Submit("Save All Services", ApplicationPermissions.ManageContract, new { name = "submitButton" })%>
<table width="100%" class="edit_restaurant_form">
<col width="19%" />
<col width="30%" />
<col width="19%" />
<col width="*" />
foreach (var item in Model)
{
%>
<tr>
<th>
<label for="DateFrom">
Effective from:</label> <label class="mandatory">* </label>
</th>
<td>
<% string dtFrom = "";
dtFrom = item.Datefrom.ToString("dd-MMM-yyyy");
%>
<%= Html.TextBox("DateFrom", dtFrom)%>
</td>
<th>
<label for="DateTo">
Effective to:</label> <label class="mandatory">* </label>
</th>
<td>
<% string dtTo = "";
dtTo = item.Dateto.ToString("dd-MMM-yyyy");
%>
<%= Html.TextBox("DateTo", dtTo)%>
</td>
</tr>
<% }
%>
here is the controller code.
public ActionResult MyController(string submitButton, IList<CMS.Model.VcmsRestaurant> AddendumMealRates)
{
// Need to receiv all value in list which is edited
return View(#"~\index.aspx", AddendumMealRates);
}
How I will get the the value in MyController which user will edited on the page?
You create a method in the controller, that will catch the postback.
If it's simple data you can do something like:
public ActionResult EditRestaurant(string dateFrom, string dateTo)
{
// do something with the values here.
}
Or Create a viewmodel, that can encapsulate more complex data:
public ActionResult EditRestaurant(EditRestaurantViewModel editRestaurantVM)
{
// do something with the values here.
}
As I can see that you are trying to postback a list of items, in a table, I'll add this to my answer:
As far as I know, you can't easily post that structure of data back, you will either need to use a javascript library like Knockout.js, or use raw javascript/jquery to gather the data, and send it back by AJAX.
Here i found the ans.
public ActionResult EditRestaurant(IList<string> dateFrom, IList<string> dateTo)
{
// do something with the values here.
}
Related
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);
}
I am creating a model which is intended to hold a table. The table will hold an arbitrary number of rows defined at run-time. I am wondering if there's an easy way to define this in MVC?
Currently all I have is:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CableSolve.Web.Models.Orders.ActivityDetailsModel>" %>
<div id="ActivityDisplay">
<table id="ActivitiesGrid">
</table>
<div id="ActivitiesGridPager"></div>
</div>
In a different model, I create a table which had a static number of rows. This was pretty easy:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CableSolve.Web.Models.Orders.OrderDetailsModel>" %>
<fieldset class="collapsible">
<legend>
<%= Html.DisplayFor(model => model.OrderDetailsLegendName)%>
</legend>
<table id="OrderDetailsContentTable" class="ContentTable">
<tr>
<td><%= Html.DisplayFor(model => model.OrderID.Name)%></td>
<td><%= Html.DisplayFor(model => model.OrderID.Value)%></td>
<td><%= Html.DisplayFor(model => model.Comment.Name)%></td>
<td><%= Html.DisplayFor(model => model.Comment.Value)%></td>
</tr>
...
So, any ideas on how I could go about having an arbitrary number of rows in ActivitiesGrid?
Basically, my controller is going to get some information at run-time and I want to display the retrieved information in a table, but I do not know how many rows of information I am going to receive.
As a light-weight solution without introducing third-party stuff (for now, if it proves necessary I will):
public class ActivityDetailsModel
{
public List<ActivityRow> ActivityRows = new List<ActivityRow>();
public struct ActivityRow
{
public DateTime? Date;
public string Person;
public string OrderOrTaskID;
public string Activity;
public ActivityRow(DateTime? date, string person, string orderOrTaskID, string activity)
{
Date = date;
Person = person;
OrderOrTaskID = orderOrTaskID;
Activity = activity;
}
}
public ActivityDetailsModel(IEnumerable<Activity> activities)
{
foreach(Activity activity in activities)
{
string orderOrTaskID = activity.TaskID != 0
? activity.OrderID + "-" + activity.TaskID
: activity.OrderID.ToString();
string activityDescription = string.Format("OldValue: {0}, NewValue: {1}", activity.OldValue,
activity.NewValue);
ActivityRows.Add(new ActivityRow(activity.UpdateDateTime, activity.UpdateUsername, orderOrTaskID, activityDescription));
}
}
}
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CableSolve.Web.Models.Orders.ActivityDetailsModel>" %>
<div id="ActivityDisplay">
<table id="ActivitiesGrid">
<%foreach (var activityRow in Model.ActivityRows)
{%>
<tr>
<td><%= Html.DisplayForModel(activityRow.Date)%></td>
<td><%= Html.DisplayForModel(activityRow.Person)%></td>
<td><%= Html.DisplayForModel(activityRow.OrderOrTaskID)%></td>
<td><%= Html.DisplayForModel(activityRow.Activity)%></td>
</tr>
<%}%>
</table>
<div id="ActivitiesGridPager"></div>
</div>
Is this relatively understandable? I hate the mark-up with all the angle-brackets and percent signs, but the project hasn't been developer with the alternative syntax.
Since you're after something dynamic, you can take advantage of existing helpers like MVC WebGrid helper or even MvcContrib Grid. These helpers will take care of generating a table containing the columns you want. There's no need to write the table by hand since it'll be dynamically generated during runtime according to the number of objects present in your datasource.
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.
I would like to pass a date from a drop down list to my ID in the Html.BeginForm. This is what I have so far.
<%using (Html.BeginForm("Inquiry", "Billing", new { Date = ????? }, FormMethod.Post))
<select id="myList" name="myList" >
<option>Term - Balance</option>
foreach (var item in Model.Term)
{ %>
<option value="/<%=String.Format("{0:yyyyMMdd}", item.Date) %>" >
<%=item.Date.ToShortDateString()%> - <%=String.Format("{0:C}", (item.Balance))%></option>
<% } %>
</select>
Any suggestions?
You can add additional attributes to the BeginForm method like this:
<% using (Html.BeginForm("Inquiry", "Billing",
FormMethod.Post, new { id = myDate.ToString() }))
{ %>
...
<%} %>
If you're asking how to make the form ID change when a user changes the selection on a dropdownlist on the form, then you'll need to use javascript for that. The code above only runs once at render time, so if your myDate variable isn't set by then, then you can't get it on the server side.
I want to load some html data dynamically from the server (like a grid composed by lots f and ) using jQuery.
At the moment I load it like this:
$("#Ricerca_Div_ContenitoreRisultati table tbody").load("/Segnalazioni/CercaSegnalazioni/3");
and generate it like this:
public ActionResult CercaSegnalazioni(int flag, string sort)
{
[..]
XElement SegnalazioniTrovate = Models.Segnalazioni.Recupera(flag, sortVal);
string ritorno = "";
bool alterna = false;
foreach (XElement segnalazione in SegnalazioniTrovate.Elements("dossier"))
{
ritorno += alterna? "<tr>" : "<tr class = \"alternata\">";
ritorno += String.Format(#"
<td><span style=""white-space: nowrap"">{0}</span></td>
<td><span style=""white-space: nowrap"">{1}</span></td>
<td style =""display : none"">{2}</td>
<td><span style=""white-space: nowrap"">{3}</span></td>
<td><span style=""white-space: nowrap"">{4}</span></td>
<td><span style=""white-space: nowrap"">{5}</span></td>
</tr>",
(string)segnalazione.Element("NUM_DOSSIER") ?? "",
(string)segnalazione.Element("ANAG_RAGSOC_CGN") ?? "",
(string)segnalazione.Element("ID_RIFATT_SEGN0") ?? "",
Tools.DecodificaStatus(int.Parse((string)segnalazione.Element("FLG_STATUS") ?? "")),
Tools.RmuoviTime((string)segnalazione.Element("DT_ACCADIMENTO")?? ""),
(string)segnalazione.Element("COD_RAMO_LUNA") ?? ""
);
alterna = !alterna;
}
return Content(ritorno);
}
Or, simply put, I make up the HTML code server side with a very messy code I don't like and return it back so that it is ready to be used client-side.
Any better / cleaner solution?
Thanks
There's different ways of doing this, and although none of them end up looking perfectly clean, the one that works best for me is to do the HTML construction on the client side. The server can return an object that works well in javascript (let's say, List<Segnalazione>) and then the client-side handler does things like:
$(list).each(function() {
var tr = $('<tr />').append(
$('<td />').css('white-space', 'nowrap').text(this.NUM_DOSSIER)
).append(
$('<td />').css('white-space', 'nowrap').text(this.ANAG_RAGSOC_CGN)
)
$("#Ricerca_Div_ContenitoreRisultati table tbody").append(tr);
});
Obviously, I'm oversimplying your output, but hopefully that gives you the idea.
If nothing else, doing it in jquery gives you the automatic escaping of values within the 'text', 'attr', and 'css' methods rather than the HttpUtility.HtmlEncode, AttributeEncode methods that would clutter up your output in C#
The cleaner solution will be creating separate View and using more CSS:
UPDATED:
In case of Request.IsAjaxRequest() use PartialView:
Controller:
public ActionResult CercaSegnalazioni(int flag, string sort)
{
[..]
XElement SegnalazioniTrovate = Models.Segnalazioni.Recupera(flag, sortVal);
return PartialView("YourPartialView", SegnalazioniTrovate);
}
YourPartialView.ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<XElement>" %>
<% bool alterna = false; %>
<table id="yourTableId">
<% foreach (XElement segnalazione in SegnalazioniTrovate.Elements("dossier")) { %>
<tr class="<%= alterna ? "alternata" : "" %>">
<% alterna = !alterna; %>
<td>
<span><%= (string)segnalazione.Element("NUM_DOSSIER") ?? "" %></span>
</td>
<td>
<span><%= (string)segnalazione.Element("ANAG_RAGSOC_CGN") ?? "" %></span>
</td>
<td class="nodisplay">
<%= (string)segnalazione.Element("ID_RIFATT_SEGN0") ?? "" %>
</td>
<td>
<span><%= Tools.DecodificaStatus(int.Parse((string)segnalazione.Element("FLG_STATUS") ?? "")) %></span>
</td>
<td>
<span><%= Tools.RmuoviTime((string)segnalazione.Element("DT_ACCADIMENTO")?? "") %></span>
</td>
<td>
<span><%= (string)segnalazione.Element("COD_RAMO_LUNA") ?? "" %></span>
</td>
</tr>
<% } %>
</table>
CSS:
table#yourTableId td span {
white-space: nowrap
}
.nodisplay {
display : none
}
Your best bet is probably to de-couple the presentation from the data. This would mean avoiding having any presentation code (ie. HTML generation) in your controller.
There are 2 ways to handle this...
Nested Partial Views
Partial Views can render... other partial views. Consider something like this...
<body> Page
-- <div> Partial View "parent" (does a RenderPartial of these:)
---- <div> Partial View "child" (piece 1) </div>
---- <div> Partial View "child" (piece 2) </div>
The parent partial view simply contains RenderPartials for the children. In addition, each patial view can end up having it's own URL (/controller/parent/, /controller/child-1/, etc.). In jQuery whenever you trap an event that needs to update the UI, you can simply ajax.load the piece you need and plug it into the div.
JSON -> jQuery Render
The other way is you forgo the server creating any presentation code, and you simply have an API that returns JSON. jQuery then accepts the incoming data objects and figures out what to do with them. Depending on the complexity of what needs to be rendered on the client side, this could be easier. This has the advantage of also allowing the same server-side code to be re-used in other ways. The downside is the content won't be indexed by search engines.