Which is the best way to pass the Html String block from Controller to View in MVC. I want it display that html block at the page load. Thank you. It can be any Html,
e.g
<table style="width:300px">
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
I want to pass this as a string from controller to View. where it will be displayed as an html.
Thank you.
In your controller action :
ViewBag.HtmlStr = "<table style=\"width:300px\"><tr><td>Jill</td><td>Smith</td> <td>50</td></tr><tr><td>Eve</td><td>Jackson</td><td>94</td></tr></table>";
Your view :
#Html.Raw(ViewBag.HtmlStr)
You can assign the html in controller to ViewBag and access the ViewBag in View to get the value that is the html
Controller
ViewBag.YourHTML = htmlString;
View
<div> #ViewBag.YourHTML </div>
Its better to not to pass the html from controller to View rather pass the object or collection of object to View (strongly typed view) and render html in View as it is responsibility of View
Controller
public ActionResult YourView()
{
//YourCode
return View(entities.yourCollection.ToList());
}
Veiw
<table style="width:300px">
foreach (var yourObject in Model)
{
<tr>
<td>#yourObject.FirstName</td>
<td>#yourObject.LasttName</td>
<td>#yourObject.Amount</td>
</tr>
}
</table>
Best approach will be to create a partial view and append the html returned by it in your parent view inside some container div.
In your main view do like this:
<div>
#{
Html.RenderAction("youraction","yourcontroller")
}
</div>
in your action do this:
public ActionResult youraction()
{
return View();
}
and your partial view:
#{
Layout = null;
}
<table style="width:300px">
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
Controller
ViewBag.HTMLData = HttpUtility.HtmlEncode(htmlString);
View
#HttpUtility.HtmlEncode(ViewBag.HTMLData)
You can use ViewBag.YourField or ViewData["YourStringName"] and for retreiving it in your View. Just place it where you want preceded by # like this #ViewBag.YourField or #ViewData["YourStringName"].
Related
Overview:
I am essentially building a single page application. Three inputs and two tables that load based on the inputs' data.
Each table is set to a tab and each tab has a button to load their respective table's data. One table is set in a partial view. I'm trying this out to see if it works so I can set both of the tables to a partial view.
Problem:
The partialview is loading the table into a new window when I click the submit button.
Example:
So, upon loading the web application, for example, 'http://localhost:30000/CommissionDatas/' the Index page loads the page and the empty tables just fine.
I am using a ViewModel because each table uses a different model and I will get an error about the Partial view table having a different data model.
Once I click the button "gpmbutton", for the partial view table, the buttion uses the 'formmethod' attribute to call actionresult method '_TrueUp' and it will retrieve the data and return the data model to the partial view. But, the partial view's table and it's data ends up posting the to 'http://localhost:30000/CommissionDatas/_TrueUp', which is a completely new page.
I have already tried changing the actionresult method type to PartialViewResult and changing the return type from 'PartialView()' to a 'View' in the controller and that still did not work. I've also tried using #Partial in the index page as well as #RenderPartial for the partial view and I get the same result.
Also, both the 'Index' and the '_TrueUp' PartialView page are in the same folder under 'CommissionDatas' in the views folder.
Please HELP!
P.S. I removed the code that is not essential to the problem as the data is sensitive.
Index.cshtml
-------------------------------------------------------------
#model CommissionReport.Models.ViewModels.CommissionViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input type="submit" ID="commissionbutton"
formaction="ReturnCommissionData"
formmethod="post"
/>
#if (Model != null)
{
<table id="mainTable" class="ui striped selectable table">
<thead>
<tr>
</tr>
</thead>
<tbody>
#foreach (var item in Model.CommissionData)
{
<tr>
</tr>
}
</tbody>
</table>
}
<input type="submit" class="btn btn-primary" ID="gpmbutton"
formaction="_TrueUp" formmethod="post"
/>
<div>
#if (Model != null)
{
Html.RenderPartial("_TrueUp");
}
</div>
</body>
</html>
This is the Partial View
_TrueUp.cshtml
----------------------------------------------------------------------------
#model CommissionReport.Models.ViewModels.CommissionViewModel
#{
Layout = null;
var trueupmodel = Model.TrueUp;
}
#if (Model != null)
{
<table id="mainTable" class="ui striped selectable table">
<thead>
<tr>
</tr>
</thead>
<tbody>
#foreach (var item in Model.TrueUp)
{
<tr>
</tr>
}
</tbody>
</table>
}
This is the Controller.
private CommissionViewModel vm = new CommissionViewModel();
[HttpPost]
public ActionResult ReturnCommissionData(FormReturn form)
{
//Code to return data here
vm.CommissionData = db.CommissionDatas.ToList();
return View("Index", vm);
}
<HttpPost>
public ActionResult _TrueUp(FormReturn form)
{
//Code For Data to be returned here
vm.TrueUp = model;
return PartialView("_TrueUp", vm);
}
Please try #Html.Action("yourAction", "yourController") instead of #Html.RenderPartial("_TrueUp").
For further information visit:
How can I use Html.Action?
MSDN
EDIT:
Use: #Html.Partial("partialViewName", partialViewModel) partialViewModel is optional.
In your case: #Html.Partial("_TrueUp").
I'm trying to make a table using partial view from another view.
the content of the view I want to desplay:
#model Agro1.ModelView.MessageViewModel
#using Agro1.Models
<span style="color:darkgreen">Messages</span>
<br />
<table>
<tr>
<td>Subject</td>
<td>Content</td>
<td>Farmer Email</td>
</tr>
#{
foreach (Message obj in Model.messages)
{
<tr>
<td>#obj.Subject</td>
<td>#obj.Content</td>
<td>#obj.FarmerEmail</td>
</tr>
}
}
</table>
in another view I want to desplay only the 5 first rows of this table.
now my code in the view looks like this:
#Html.Partial("DisplyaMessages",Model)
and it shows the full table.
how can I desplay only the 5 first rows?
t
You could use linq syntax .take(5) either in the controller action or in the razor.
Your razor code would look like this:
#{
foreach (Message obj in Model.messages.take(5))
{
<tr>
<td>#obj.Subject</td>
<td>#obj.Content</td>
<td>#obj.FarmerEmail</td>
</tr>
}
You should add a new property into the model with the max rows to display.
After that you can check this property during the foreach.
#model Agro1.ModelView.MessageViewModel
#using Agro1.Models
<span style="color:darkgreen">Messages</span>
<br />
<table>
<tr>
<td>Subject</td>
<td>Content</td>
<td>Farmer Email</td>
</tr>
#{
var x = 0;
foreach (Message obj in Model.messages)
{
if (Model.MaxRows > 0 && x > Model.MaxRows) break;
<tr>
<td>#obj.Subject</td>
<td>#obj.Content</td>
<td>#obj.FarmerEmail</td>
</tr>
x++;
}
}
</table>
You can call the partial creating a new model like this:
#Html.Partial("DisplyaMessages", new MessageViewModel { MaxRows = 5, messages = Model.messages})
I have this view based on a list of a model where I create strongly-typed checkboxes for each items of the model based on a boolean.
Here's my view:
#using MyApp.Models
#model IList<MyApp.Models.ObjInfo>
#{
ViewBag.Title = "Obj Inventory";
}
<h2>Search Inventory</h2>
<p>
#using (Html.BeginForm())
{
(Many search filters which are non-relevant)
<p>
Send Items: #Html.ActionLink("Click Here", "SendItems")
</p>
}
<table>
<tr>
<th>
Obj Name
</th>
<th>
Number In Stock
</th>
(...)
<th>
Select Item
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.OtherObj.m_Name)
</td>
(...)
<td>
#Html.CheckBoxFor(modelItem => item.m_IsSelected)
</td>
</tr>
}
</table>
The whole process works fine and I can actually generate a view with checkboxes for each item of my list of model.
Now my question is that I want to create a list which would regroup only the items in the list which are checked and send them to the controller. How could I do that? Can anyone help me or suggest me a way to work?
Thank you!
* EDIT *
Here is the HttpPost Method used to get the List of items as mentioned below:
//
// GET: /Inventory/SendItems
[HttpPost]
public ActionResult SendItems(IList<ObjInfo> listToSend)
{
m_ListObjToSend = new List<ObjInfo>();
foreach (var item in listToSend.Where(item => item.m_IsSelected))
{
m_ListObjToSend .Add(item);
}
return View(m_ListObjToSend );
}
However I have encountered many problems:
This method does NOT work if I put the [HttpPost] attribute (it will show as "Not Found");
The list I am supposed to receive is null;
Each hiddenfield linked with the checkbox has default value as false even if the checked value shows true;
I am using an actionlink because I do not want to use a button, there is already one that is doing another job.
I am open for any comments / help available, thank you!
If you use the CheckBoxFor helper to generate checkboxes you will notice that it generates an additional hidden field along with each checkbox. This means that all values will be sent to the controller and you will have to filter in your controller those that are checked.
Also I would recommend you using indexes to ensure proper model binding. You just need to use an IList<ObjInfo> or ObjInfo[] which is trivially easy achievable by calling .ToList() or .ToArray() extension methods on your view model before passing it to the view:
#using MyApp.Models
#model IList<ObjInfo>
...
#for (var i = 0; i < Model.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(x => x[i].OtherObj.m_Name)
</td>
(...)
<td>
#Html.CheckBoxFor(x => x[i].m_IsSelected)
</td>
</tr>
}
...
And now your controller action could directly take the list of items:
[HttpPost]
public ActionResult SomeAction(IEnumerable<ObjInfo> model)
{
...
}
and if you wanted to find the selected values, you could simply get them through LINQ:
[HttpPost]
public ActionResult SomeAction(IEnumerable<ObjInfo> model)
{
var selectedItems = model.Where(x => x.m_IsSelected);
...
}
Remark: m_Name and m_IsSelected is a disastrously bad naming convention for a properties in C#.
UPDATE:
Another issue you have with your code is that your Html.BeginForm doesn't contain any input field. It has only a single ActionLink which obviously only does a GET request. If you want to submit the values you should wrap your entire table with the form and use a submit button and not some action links:
#using MyApp.Models
#model IList<ObjInfo>
#{
ViewBag.Title = "Obj Inventory";
}
<h2>Search Inventory</h2>
<p>
#using (Html.BeginForm("SendItems", null, FormMethod.Post))
{
(Many search filters which are non-relevant)
<table>
<tr>
<th>Obj Name</th>
<th>Number In Stock</th>
(...)
<th>Select Item</th>
</tr>
#for (var i = 0; i < Model.Count; i++)
{
<tr>
<td>
<!--
This will not be sent to your controller because it's only a label.
You will need a corresponding hidden field if you want to get that value back
-->
#Html.DisplayFor(x => x[i].OtherObj.m_Name)
</td>
(...)
<td>
#Html.CheckBoxFor(x => x[i].m_IsSelected)
</td>
</tr>
}
</table>
<p>
Send Items: <button type="submit">Click Here</button>
</p>
}
</p>
So really, 2 things you should learn:
The naming convention that the default model binder expects when binding to a list
How to use a javascript debugging tool (such as FireBug and/or Chrome Developper Toolbar) which will allow you to inspect all the values that are sent to your server and immediately recognized whether you respected the convention you learned in 1.
I'm using the guide found here http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style and am using MVC2.
I've got it working with a controller method as such:
[HttpPost]
public ActionResult CreateStockRequest(StockRequestModel viewModel, List<StockRequestModel.StockRequestItem> items)
{
viewModel.Items = items;
// Validate the request and submit it
return View(viewModel);
}
As you can see, even though my Model contains an Items method, i've had to add an items parameter, as the property on the model wasn't getting populated.
I've tried changing items to Items in the BeginCollectionItem method and have tried various other values but I can't get it to work without adding the seperate items parameter in the controller method.
tl;dr: How can I add/remove/edit items in a list property of a model, from a view?
View
<table>
<thead>
<tr>
<td><%= Html.LabelFor(m => m.Items[0].Item )%></td>
<td><%= Html.LabelFor(m => m.Items[0].Quantity )%></td>
</tr>
</thead>
<tbody id="editorRows">
<% foreach (var item in Model.Items)
{
Html.RenderPartial("StockRequestItemEditor", item);
}%>
</tbody>
<tfoot>
<tr><td colspan="2"> </td></tr>
<tr>
<td colspan="2"><%= Html.ActionLink("Add Item...", "BlankEditorRow", null, new { id = "addItem" })%></td>
<script type="text/javascript">
$("#addItem").click(function() {
$.ajax({
url: this.href,
cache: false,
success: function(html) { $("#editorRows").append(html); }
});
return false;
});
</script>
</tr>
</tfoot>
</table>
Partial View
<tr>
<% using(Html.BeginCollectionItem("Items")) { %>
<td>
<%= Html.ComboBoxFor(m => m.Item,
null,
Url.Action("Products", "Data", new { area = (string)null }),
Model.Item,
2)%>
</td>
<td><%= Html.TextBoxFor(m => m.Quantity)%></td>
<% } %>
</tr>
It's a long shot but maybe this is the problem:
Html.RenderPartial("StockRequestItemEditor", item);
I noticed when inspecting the viewModel in the POST action that it would have the correct number of items in the collection, but they would all be null. That suggests to me that this is a prefixing issue with the model binder. So maybe something like this will work:
var dictPrefix = new ViewDataDictionary();
dictPrefix.TemplateInfo.HtmlFieldPrefix = "SomePrefix";
Html.RenderPartial("StockRequestItemEditor", item, dictPrefix);
I don't think RenderPartial() passes along the prefix without using this overload (might be wrong though). I'm not completely sure how the bind prefixing works, so I don't actually know what the name would be, but it seems like it's relevant here. The collection definitely has the correct number of items for me, but none of them are correctly bound.
Hopefully this will be enough to push someone else to giving you the right answer.
Why don't you use a view model?
public class StockRequestModel
{
public List<StockRequestItem> Items { get; set; }
... some other properties
}
and then have your controller action take this view model as parameter:
[HttpPost]
public ActionResult CreateStockRequest(StockRequestModel viewModel)
{
// TODO: do something with viewModel.Items ...
return View(viewModel);
}
and inside your view:
<div class="editorRow">
<% using(Html.BeginCollectionItem("Items")) { %>
...
<% } %>
</div>
Problem is : I do have Index.cshtml as
#{
ViewBag.Title = "Search";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="#Url.Content("../../Scripts/jquery.unobtrusive-ajax.min.js") type="text/javascript"></script>
<h2>Answer's are </h2>
<div id="result">
#Ajax.ActionLink("Search Wiki",
"WikiAns",
new AjaxOptions{
UpdateTargetId = "result",
InsertionMode=InsertionMode.Replace,
HttpMethod="GET",
LoadingElementId="progress"
})
</div>
<div id="progress" style="display: none">
<img src="#Url.Content("../../Content/Images/ajax-loader.gif")" alt="loader" />
</div>
Now i do have partial view model _WikiAns:
#model IEnumerable<Questions.Models.WikiAnsClass>
<h2>Our Links</h2>
<table>
#foreach (var item in Model) {
<tr>
<td>
#item.content
</td>
</tr>
}
</table>
Now using above i want is that...on clicking Search Wiki action link, id="result" get all partial view rendered in it. But its not happening. Instead of its going to a page "localhost:80/Search/WikiAns" and showing the result there. but i want to it to stay at localhost:80/Search and replace its "result" id. but its not working this way.
Here is my action called WikiAns
public ActionResult WikiAns()
{
//Code to follow...
var wikians = //code to follow
return PartialView("_wikiAns", wikians);
}
What's the problem ?
Also how can i implement this Ajax GIF loader...i mean showing it while action gets executed. ?
Please suggest
Thanks
#Pbirkoff may be right about this but you can go through my post of very easy to implement demo of your scenario and build it up from there.
http://mazharkaunain.blogspot.com/2011/05/aspnet-mvc-razor-render-partial-view.html
http://mazharkaunain.blogspot.com/2011/04/aspnet-mvc-render-partial-view-using.html
You need to include Microsoft Ajax scripts at your page or layout.