I have a mvc web application which contains chart and table data.
Scenario:
I am populating data in the Index method and return the model to view for binding. In view, table bind with the data. I also want to bind the chart with same data. Chart bind with child action. I set TempData[] object in the Index method and retrieve the same in Chart action.
Code:
Controller
public ActionResult Index()
{
var data = new List<MyModel>()
{
new MyModel { Text = "Name1", Value = 123 },
new MyModel { Text = "Name2", Value = 24 },
};
TempData["data"] = data;
return View(data);
}
public FileContentResult Chart()
{
List<MyModel> data = TempData["data"] as List<MyModel>;
var chart = new Chart
{
Width = 300,
Height = 450,
};
if (data != null)
{
chart.ChartAreas.Add("");
chart.Series.Add("");
chart.Series[0].ChartType = SeriesChartType.Column;
foreach (var q in data)
{
chart.Series[0].Points.AddXY(q.Text, Convert.ToDouble(q.Value));
}
}
using (var chartimage = new MemoryStream())
{
chart.SaveImage(chartimage, ChartImageFormat.Png);
return File(chartimage.GetBuffer(), #"image/png");
}
}
public async Task<ActionResult> Export()
{
var converter = new HtmlToPdf();
var baseAddress = new Uri("http://localhost:4545/");
var cookieContainer = new System.Net.CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (HttpClient client = new HttpClient(handler) { BaseAddress = baseAddress })
{
var result = await client.GetAsync("/Home/Index");
var htmlString = await result.Content.ReadAsStringAsync();
var doc = converter.ConvertHtmlString(htmlString, baseAddress.ToString());
doc.Save(System.Web.HttpContext.Current.Response, true, "test.pdf");
doc.Close();
}
return null;
}
View:
<div class="row">
#using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
<div class="col-md-12">
<table>
#{
foreach (var item in Model)
{
<tr>
<td>
#item.Text
</td>
<td>
#item.Value
</td>
</tr>
}
}
</table>
</div>
<div class="col-md-12">
<img src="#Url.Action("Chart")" />
<input type="submit" value="Filter" />
</div>
}
<div class="col-md-12">
#using (Html.BeginForm("Export", "Home", FormMethod.Post))
{
<input type="submit" value="Export" />
}
</div>
Problem:
Here i am using SelectPdf to export the web page to pdf. When i click Export button, it takes the content of web page so that again Index and Chart rendered. But here i didn't get tempdata[] values. It shows as null. So chart data not getting in pdf
Please help me to solve this issue
Please Note :
TempData in ASP.NET MVC can be used to store temporary data which can be used in the subsequent request. TempData will be cleared out after the completion of a subsequent request.
So to retain the values of TempData in subsequent request you need to call either TempData.Keep() or Peek("tempdata name").
Keep Syntax:
String data = TempData["myData"] as string;
TempData.Keep();
Peek Syntax:
String data = TempData.Peek("myData");
Try this
List<MyModel> data = (List<MyModel>)TempData.Peek("data");
Controller Json result
public JsonResult GetStaffJson( string Branch)
{
List<SelectListItem> S_li = new List<SelectListItem>();
try
{
TempData["Staff_List"] =S_li = cmnclass.Get_staff_SelectList(Branch);
}
catch (Exception ex)
{
logger.LogError(ex);
}
finally
{
}
return Json(S_li, JsonRequestBehavior.AllowGet);
}
View
#Html.DropDownListFor(m => m.clsAUDIT.Branch, ViewBag.Branch_list as IEnumerable<SelectListItem>,"Select a Branch", new {#id="ddlBranch", #class = "form-control", #actor = "DropDown" })
And
#Html.DropDownListFor(m=>m.clsCGT.fo_Name_CGT, TempData["Staff_List"] as IEnumerable<SelectListItem> , new {#id="ddl_CGT_fo",#class="input-sm", #actor = "DropDown", #style = "width:auto;" })
Two more
#Html.DropDownListFor(m => m.clsGRT.GRT_fo_Name, TempData["Staff_List"] as IEnumerable<SelectListItem>, new {#id="ddl_GRT_fo", #class = "input-sm", #actor = "DropDown", #style = "width:auto;" })
#Html.DropDownListFor(m => m.clsGRT.GRT_bm_name, TempData["Staff_List"] as IEnumerable<SelectListItem>, new { #id = "ddl_GRT_bm", #class = "input-sm", #actor = "DropDown", #style = "width:auto;" })
Now Jquery
$('#ddlBranch').change(function () {
var url = '#Url.Action("GetStaffJson", "Annex1")';
var Branch = $("#ddlBranch").val();
var ddl_CGT_fo = $("#ddl_CGT_fo");
var ddl_GRT_fo = $("#ddl_GRT_fo");
var ddl_GRT_bm = $("#ddl_GRT_bm");
$.getJSON(url, { Branch: Branch }, function (response) {
ddl_CGT_fo.empty();
ddl_GRT_fo.empty();
ddl_GRT_bm.empty();
debugger;
$.each(response, function (index, item) {
debugger;
var p = new Option(item.Text, item.Value);
ddl_CGT_fo.append(p);
ddl_GRT_fo.append(p);
ddl_GRT_bm.append(p);
});
});
});
On change of ddlBranch I am populating three DropDownList's
ddl_CGT_fo
ddl_GRT_fo
ddl_GRT_bm
Its working fine but only populating last DropDownList ' ddl_GRT_bm' ,
What I am missing here ? why first two DropDownList Still empty ?
You should use the .clone() function for the new created option while appending it.
var p = new Option(item.Text, item.Value);
ddl_CGT_fo.append($(p).clone());
ddl_GRT_fo.append($(p).clone());
ddl_GRT_bm.append($(p).clone());
I've read a bunch of questions about the subject but haven't managed to find a solution to this specific problem.
Controller
public ActionResult Index() {
string categorie = "--Tout--";
string souscategorie = "--Tout--";
if (Session["Categorie"] != null) {
categorie = Session["Categorie"].ToString();
}
if (Session["SousCategorie"] != null) {
souscategorie = Session["SousCategorie"].ToString();
}
SelectList cats = new SelectList(GetCategories(), categorie);
SelectList sCats = new SelectList(GetSousCategories(), souscategorie);
ViewBag.Categories = cats;
ViewBag.SousCategories = sCats;
using(DAL.WebShopEntities entities = new WebShopEntities()) {
return View(entities.Article.ToList());
}
}
View
#Html.Label("Catégories")
#Html.DropDownList("Categories", (SelectList)ViewBag.Categories, new { #class = "form-control dropdownlist" })
<br />
#Html.Label("Sous-Catégories")
#Html.DropDownList("SousCategories", (SelectList)ViewBag.SousCategories, new { #class = "form-control dropdownlist" })
When debugging the view I can see clearly that the option stocked in the session is sent to the View. But it displays the index 0 when checking in the browser. This has me bugging because the SelectList behaves normally, I think the problem lays with the DropDown but what could be the problem?
Can you try to change your Viewbag property name and try again?
try Categories => CategoriesList and
SousCategories=> SousCategoriesList
public ActionResult Index() {
string categorie = "--Tout--";
string souscategorie = "--Tout--";
if (Session["Categorie"] != null) {
categorie = Session["Categorie"].ToString();
}
if (Session["SousCategorie"] != null) {
souscategorie = Session["SousCategorie"].ToString();
}
SelectList cats = new SelectList(GetCategories(), categorie);
SelectList sCats = new SelectList(GetSousCategories(), souscategorie);
ViewBag.CategoriesList = cats;
ViewBag.SousCategoriesList = sCats;
using(DAL.WebShopEntities entities = new WebShopEntities()) {
return View(entities.Article.ToList());
}
}
#Html.Label("Catégories")
#Html.DropDownList("Categories", (SelectList)ViewBag.CategoriesList, new { #class = "form-control dropdownlist" })
<br />
#Html.Label("Sous-Catégories")
#Html.DropDownList("SousCategories", (SelectList)ViewBag.SousCategoriesList, new { #class = "form-control dropdownlist" })
I have written some code based on some tutorials to update an existing word document with data from my database tables.
I keep getting the program crashing and advising that I may have an infinite loop, however I am using a for each statement and when I debug it tells me i only have one record. Cannot understand where the problem is.
If someone can assist that would be greatly appreciated. Code below
Controller
using System.Web.Mvc;
using Mojito.Models;
namespace Mojito.Controllers
{
public class KronosDesignDocumentController : Controller
{
private MojitoContext _db = new MojitoContext();
//
// GET: /KronosDesignDocument/
public ActionResult Index()
{
ViewBag.CustomerId = new SelectList(_db.Customers, "CustomerId", "CustomerName");
return View();
}
[HttpPost]
public ActionResult Load(int customerId)
{
var kronosDesignTemplate = new KronosDesignDocument.CreateDesignDoc(#"C:\Users\Craig Cocker\Documents\XML Files\Test_Design_Template.docx");
kronosDesignTemplate.CustomerDesignDocument();
ViewBag.CustomerId = new SelectList(_db.Customers, "CustomerId", "CustomerName");
ViewBag.Message = "Configuration has been loaded successfully";
return View("Index");
}
}
}
Model
using System.Collections.Generic;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System.Linq;
namespace Mojito.Models
{
public class KronosDesignDocument
{
public static MojitoContext _db = new MojitoContext();
public class CreateDesignDoc
{
private readonly string _xmlPath;
//private readonly int _customerId;
public CreateDesignDoc(string pathToXmlFiles)
{
_xmlPath = pathToXmlFiles;
}
public IEnumerable<Customer> CustomerDesignDocument()
{
WordprocessingDocument myDoc = WordprocessingDocument.Open(_xmlPath, true);
var docPart = myDoc.MainDocumentPart;
var doc = docPart.Document;
var table = new Table();
var tb = new TopBorder();
tb.Val = BorderValues.DashDotStroked;
tb.Size = 12;
var borders = new TableBorders();
borders.TopBorder = tb;
borders.LeftBorder = new LeftBorder() {Val = BorderValues.Single, Size = 12};
borders.RightBorder = new RightBorder() {Val = BorderValues.Single};
borders.BottomBorder = new BottomBorder() {Val = BorderValues.Single};
borders.InsideHorizontalBorder = new InsideHorizontalBorder() {Val = BorderValues.Single};
borders.InsideVerticalBorder = new InsideVerticalBorder() {Val = BorderValues.Single};
var props = new TableProperties();
props.Append(borders);
table.Append(props);
var customers = _db.Customers.ToList();
var customerCollection = new List<Customer>();
foreach (var c in customers)
{
var tr = new TableRow();
var customerName = c.CustomerName;
var tc = new TableCell();
var runProp = new RunProperties();
runProp.Append(new Bold());
runProp.Append(new Color() {Val = "FF0000"});
var run = new Run();
run.Append(runProp);
var t = new Text(customerName);
run.Append(t);
var justification = new Justification();
justification.Val = JustificationValues.Center;
var paraProps = new ParagraphProperties(justification);
var p = new Paragraph();
p.Append(paraProps);
p.Append(run);
tc.Append(p);
var tcp = new TableCellProperties();
var tcw = new TableCellWidth();
tcw.Type = TableWidthUnitValues.Dxa;
tcw.Width = "2000";
tcp.Append(tcw);
tcp.Append(tcp);
tr.Append(tc);
table.Append(tr);
}
doc.Body.Append(table);
doc.Save();
return customerCollection;
}
}
}
}
View
#model Mojito.Models.KronosDesignDocument
#{
ViewBag.Title = "Kronos Design Document";
}
<h1>Load Kronos Data</h1>
<h2>#ViewBag.Message</h2>
#using (Html.BeginForm("Load", "KronosDesignDocument", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
<div>#Html.Partial("~/Views/Shared/_Customer.cshtml")</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" value="Create Design Document" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
In your method to create your document you have this line:
tcp.Append(tcp);
that basically appends a reference to its self. I assume the OpenXML stuff expects you to take care of peventing such self-references and if you don't it's only way it has left is break with an StackOverflow exception.
If you fix that line, to
tc.Append(tcp);
all is good...
In a view I'm using 3 dropdownlist strongly-typed to a model like this:
#using (Html.BeginForm())
{
<p>Filter by rarity: #Html.DropDownListFor(_item => _item.mRarity, Model.mRarityList, new {#id = "cardRarity"})
Filter by type: #Html.DropDownListFor(_item => _item.mType, Model.mTypeList, new {#id = "cardType"})
Filter by color: #Html.DropDownListFor(_item => _item.mColor, Model.mColorList, new {#id = "cardColor"})
</p>
}
Here's the view in which the thing is displayed:
#model PagedList.IPagedList<MvcMagicAdmin.Utilities.CardDisplay>
#{
ViewBag.Title = "Cards Display Results";
}
<h2>
Cards Display Results
</h2>
<script type="text/javascript">
$(document).ready(function () {
$('#cardRarity').change(function () {
var showCardRarity = $(this).val();
alert(showCardRarity);
var showCardType = $('#cardType').val();
var showCardColor = $('#cardColor').val();
refreshResults(showCardRarity, showCardType, showCardColor);
});
$('#cardType').change(function () {
var showCardType = $(this).val();
alert(showCardType);
var showCardRarity = $('#cardRarity').val();
var showCardColor = $('#cardColor').val();
refreshResults(showCardRarity, showCardType, showCardColor);
});
$('#cardColor').change(function () {
var showCardColor = $(this).val();
alert(showCardColor);
var showCardRarity = $('#cardRarity').val();
var showCardType = $('#cardType').val();
refreshResults(showCardRarity, showCardType, showCardColor);
});
function refreshResults(rarity, type, color) {
$.get("#Url.Action("DisplayCardsResults", "Card")", {
_page: 1,
_sortOrder: "#ViewBag._sortOrder",
_rarity: rarity,
_type: type,
_color: color,
}, function(data) {
$("#resultsDiv").html(data);
});
}
});
</script>
<div>
<div class="float-left">
<p>#Html.ActionLink("Make a new search", "SearchCardsAdvanced")</p>
</div>
<div class="float-right">
<p><span class="bold baseFontSize">Legend: </span>Details #Html.Image("~\\Images\\Functional\\Icons\\detailsIcon.jpg", "details", new { #class = "centerVert" } )
Edit #Html.Image("~\\Images\\Functional\\Icons\\editIcon.png", "edit", new {#class = "centerVert"} )
Delete #Html.Image("~\\Images\\Functional\\Icons\\trashIcon.png", "delete", new {#class = "centerVert"} )</p>
</div>
<div class="clear"></div>
</div>
#{
Html.RenderAction("FilterCardsResults", "PartialViews");
}
<div id="resultsDiv">
#{
Html.RenderPartial("ResultsTable", Model);
}
</div>
So, yes, I am calling a partial view from another controller because I pass a model which is not included in the Original List of models.
The view is generated like this:
private static readonly CardsFilters mCardsFilters = new CardsFilters();
public ActionResult FilterCardsResults()
{
return PartialView("Filters/FilterCardsResults", mCardsFilters);
}
Here's the model on which the data is built:
public class CardsFilters
{
public string mRarity { get; set; }
public IEnumerable<SelectListItem> mRarityList { get; set; }
public string mType { get; set; }
public IEnumerable<SelectListItem> mTypeList { get; set; }
public string mColor { get; set; }
public IEnumerable<SelectListItem> mColorList { get; set; }
public CardsFilters()
{
List<SelectListItem> items = new List<SelectListItem>
{
new SelectListItem() {Value = "All", Text = "All"},
new SelectListItem() {Value = "Land", Text = "Land"},
new SelectListItem() {Value = "Common", Text = "Common"},
new SelectListItem() {Value = "Uncommon", Text = "Uncommon"},
new SelectListItem() {Value = "Rare", Text = "Rare"},
new SelectListItem() {Value = "Mythic Rare", Text = "Mythic Rare"},
new SelectListItem() {Value = "Special", Text = "Special"}
};
mRarityList = new SelectList(items, "Value", "Text");
items = new List<SelectListItem>
{
new SelectListItem(){ Value = "All", Text = "All"},
new SelectListItem(){ Value = "Artifact", Text = "Artifact"},
new SelectListItem(){ Value = "Instant", Text = "Instant"},
new SelectListItem(){ Value = "Creature", Text = "Creature"},
new SelectListItem(){ Value = "Land", Text = "Land"},
new SelectListItem(){ Value = "Planeswalker", Text = "Planeswalker"},
new SelectListItem(){ Value = "Enchantment", Text = "Enchantment"},
new SelectListItem(){ Value = "Sorcery", Text = "Sorcery"},
new SelectListItem(){ Value = "Tribal", Text = "Tribal"},
};
mTypeList = new SelectList(items, "Value", "Text");
items = new List<SelectListItem>
{
new SelectListItem(){ Value = "All", Text = "All"},
new SelectListItem(){ Value = "White", Text = "White"},
new SelectListItem(){ Value = "Red", Text = "Red"},
new SelectListItem(){ Value = "Green", Text = "Green"},
new SelectListItem(){ Value = "Blue", Text = "Blue"},
new SelectListItem(){ Value = "Black", Text = "Black"},
new SelectListItem(){ Value = "Gold", Text = "Gold"},
new SelectListItem(){ Value = "Colorless", Text = "Colorless"},
};
mColorList = new SelectList(items, "Value", "Text");
}
}
And, finally, the post method called in the controller:
public ActionResult DisplayCardsResults(int? _page, string _sortOrder, string _rarity = "", string _type = "", string _color = "")
{
ViewBag._rarity = _rarity;
ViewBag._color = _color;
ViewBag._type = _type;
if (Request.HttpMethod != "GET")
{
_page = 1;
}
if (mListCards.Count == 0)
{
TempData[MessageDomain.Tags.TEMPDATA_MESSAGE_ERROR] = NODATAFILTERERRORMESSAGE;
}
int pageNumber = (_page ?? 1);
if (Request.IsAjaxRequest())
{
mListCardsToShow = GetListCardsToShow(_rarity, _color, _type);
return PartialView("ResultsTable", mListCardsToShow.ToPagedList(pageNumber, ValueDomain.PAGE_SIZE));
}
if (mListCardsToShow.Count > 0)
{
mListCardsToShow = SortListOrder(_sortOrder, mListCardsToShow);
return View(mListCardsToShow.ToPagedList(pageNumber, ValueDomain.PAGE_SIZE));
}
if (mListCards.Count > 0)
{
mListCards = SortListOrder(_sortOrder, mListCards);
}
return View(mListCards.ToPagedList(pageNumber, ValueDomain.PAGE_SIZE));
}
The dropdownlist works very fine, except for one reason. When I post back the form, all the values selected in the dropdownlist resets to "All", and I'd like to keep them selected. How might I do this?
You must make shure that you are correctly binding your return model into the view.
I took your example and included it into a simple project, that is working ok:
The controller with a simple POST:
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
var model = new CardsFiltersViewModel();
return View(model);
}
[HttpPost]
public ActionResult Index(CardsFiltersViewModel model)
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View(model);
}
public ActionResult About()
{
return View();
}
}
It returns the object the you presented above.
The View is the exact same as your code.
#using (Html.BeginForm())
{
<p>
Filter by rarity: #Html.DropDownListFor(_item => _item.mRarity, Model.mRarityList, new { #id = "cardRarity" })
Filter by type: #Html.DropDownListFor(_item => _item.mType, Model.mTypeList, new { #id = "cardType" })
Filter by color: #Html.DropDownListFor(_item => _item.mColor, Model.mColorList, new { #id = "cardColor" })
</p>
<input type="submit" name="name" value=" " />
}
With the reference to the model class object (
#model MvcApplication7.Controllers.CardsFiltersViewModel
)