How to pass Controller Element value to View(.cshtml) div element value? - asp.net-mvc

I developing WEB API project using .net C#
I need to get the value from controller.cs file and use that value into View(.cshtml) file.
My Controller Code:
HomeController.cs
XmlDocument doc = new XmlDocument();
doc.Load(httpWebResponse.GetResponseStream());
XmlElement TransID = (XmlElement)doc.SelectSingleNode("/CensusUploadResponse/TransactionID");
if (TransID != null)
{
string ResultID = TransID.InnerText;
}
I need to pass the ResultID to Index.cshtml(Ex:ResultID = 17)
MY View .cshtml file code:
Index.cshtml
<div runat="server" id="CensusuploadDiv" style="border:1px solid black; width:420px;">
</div>
I need to assign that ResultID value to CensusuploadDiv.
I try with following method using ViewBag. but's it's not working.
Assign ResultID to ViewBag like below
if (TransID != null)
{
string ResultID = TransID.InnerText;
ViewBag.Test2 = ResultID;
}
and i get the value in index file like below
<div runat="server" id="CensusuploadDiv" style="border:1px solid black; width:420px;">
#ViewBag.Test2
</div>
But value not bind to div.

I find out solution for my problem by Using TempData.
TempData help me lot...
I use TempData as follow in HomeController.cs
string result = strBind.ToString();
TempData["Result"] = result;
In view.cshtml
#TempData["Result"]
It's work fine for me...

Do you develop Web API or ASP.NET MVC project? Best way to access values from controller in view is to use strongly typed models:
#model int
<div>#Model</div>
Example:
Index.cshtml
#model int
<div>#Model</div>
HomeController.cs
public ActionResult GetId()
{
int id;
....
return View(id);
}
Please note, that WebApi and MVC controllers are slightly different. But this is how it works.

Related

How to configure an MVC dropdown depending on which view calls it

I have two views, BatchReceipt and Receipt which utilise the same model. Until now they have used the same display template of ReceiptType. But I want to have one exclude certain items and the other to have the full list (so essentially a second .cshtml display template called ReceiptTypeFull). How do I configure each of these views in Visual Studio to utilise the different Display Templates?
Some additions to show the code being used:
I have file ReceiptType.cshtml being used as a DisplayTemplate which contains the following to setup the receipt dropdown
#using Clinton.Web.Helpers.EnumHelpers
#{
var item = EnumsHelper.GetNameFromEnumValue(Model);
}
I want to use a different DisplayTemplate, call it ReceiptTypeFull.cshtml
#using Clinton.Web.Helpers.EnumHelpersFull
#{
var item = EnumsHelper.GetNameFromEnumValue(Model);
}
#item
The difference is in calling the enumhelper or the enumhelperfull to vary the query populating the dropdown. My problem is that I cannot see how to redirect the view to use the different enumhelper/displaytemplate/
Thanks
I think I understand what you are getting at. You want to control which template is used for an Enum in the view.
I will explain using editor templates but it works the same way if you use display templates. You should be able to follow and apply for your scenario.
The idea is to use this overload of the editor html helper.
public static MvcHtmlString Editor(this HtmlHelper html, string expression, string templateName);
It is called like this
#Html.Editor("{property name}", "{template name}").
Below is an example to show it being used.
Suppose we have this enum
public enum MyItems
{
Item1 = 1,
Item2 = 2,
Item3 = 3
}
This helper
public static class MyEnumHelper
{
public static List<MyItems> GetAllItems()
{
return new List<MyItems>()
{
MyItems.Item1,
MyItems.Item2,
MyItems.Item3
};
}
public static List<MyItems> GetSomeItems()
{
return new List<MyItems>()
{
MyItems.Item1,
MyItems.Item2
};
}
}
This controller
public class HomeController : Controller
{
public ActionResult AllItems()
{
return View();
}
public ActionResult SomeItems()
{
return View();
}
}
We have these 2 editor templates, which are put in views/shared/editortemplates
First one called MyItems.cshtml which is the all one
#model MyItems?
#{
var values = MyEnumHelper.GetAllItems().Cast<object>()
.Select(v => new SelectListItem
{
Selected = v.Equals(Model),
Text = v.ToString(),
Value = v.ToString()
});
}
#Html.DropDownList("", values)
Second one called MyItems2.cshtml which is the some one
#model MyItems?
#{
var values = MyEnumHelper.GetSomeItems().Cast<object>()
.Select(v => new SelectListItem
{
Selected = v.Equals(Model),
Text = v.ToString(),
Value = v.ToString()
});
}
#Html.DropDownList("", values)
Then in the AllItems.cshtml to get the MyItems.cshtml template called we need
#model MyItemsViewModel
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.MyItem)
<submit typeof="submit" value="submit"/>
}
And in the SomeItems.cshtml to get some of the items by calling MyItems2.cshtml we use
#model MyItemsViewModel
#using (Html.BeginForm())
{
#Html.Editor("MyItem", "MyItems2") #* this bit answers your question *#
<submit typeof="submit" value="submit" />
}

Object reference not set to an instance of an object in MVC5

I have an MVC5 app, and in the HomeController, I have an ActionResult defined like this:
public ActionResult BlogRSS()
{
var model = new BlogModel();
string strFeed = "http://webmysite.com/feed";
using (XmlReader reader = XmlReader.Create(strFeed))
{
SyndicationFeed rssData = SyndicationFeed.Load(reader);
model.BlogFeed = rssData;
}
return View(model);
}
Then, for this ActionResult, I created a partial view named BlogRSS, which looks like this:
#model MyApp.Models.BlogModel
#{
if (Model.BlogFeed != null)
{
<ul>
#foreach (var post in Model.BlogFeed.Items.ToList().Take(3))
{
<li><a href='#post.Links.First().Uri' target='_blank'>#post.Title.Text</a></li>
}
</ul>
}
}
And my model is defined simply like this:
public class BlogModel
{
public SyndicationFeed BlogFeed { get; set; }
}
So, the point is that I want to call that partial view in my _Layout.cshtml file, but when the website opens I get the error message specified in the title. I guess it is not calling my BlogRSS method at all. I'm calling it in the _Layout.cshtml like this:
<div class="col-md-4">
Blog
<br />
#Html.Partial("BlogRSS")
</div>
How can I solve the problem, and make sure that the corresponding ActionResult is also called before rendering the View?
The problem is that you're putting a call to a partial view which just renders the view without calling the controller and the model passed to that view is null.
There are couple ways how to fix this:
1) use Action instead of Partial
#Html.Action("BlogRSS", "Blog")
2) Define a base ViewModel which you will pass to the each view and put your feed into it.

How to get sequence/array index in Editor Template?

Case:
I have a list of items of Class X displayed using Editor Template for Class X.
Problem:
How can I get index of an item being processed on the inside of the Editor Template?
I've been using this HtmlExtension that returns only the needed id of an iteration. It's basically a regex on ViewData.TemplateInfo.HtmlFieldPrefix that's capturing the last number.
public static class HtmlExtensions
public static MvcHtmlString Index(this HtmlHelper html)
{
var prefix = html.ViewData.TemplateInfo.HtmlFieldPrefix;
var m = Regex.Match(prefix, #".+\[(\d+)\]");
if (m.Success && m.Groups.Count == 2)
return MvcHtmlString.Create(m.Groups[1].Value);
return null;
}
}
Can be used in an EditorFor-template like this:
#Html.Index()
Use a for loop instead of for each and pass the indexer into the EditorFor extension; razor should handle the rest.
#for(var i = 0; i < Model.count(); i++)
{
#Html.EditorFor(m => Model.ToArray()[i], new { index = i })
}
Update:
pass in the the index of the item using view data as show above.
In your editor template access the item via the ViewBag
<span> Item Index: #ViewBag.index </span>
Using the EditorTemplate is the best solution when viewing models that contain a list of something.
In order to find the index for the sub-model being rendered you can use the property that Razor sets by default:
ViewData.TemplateInfo.HtmlFieldPrefix
Say, for example, you have the following view models:
public class ParagraphVM
{
public int ParagraphId { get; set; }
public List<LineVM> Lines { get; set; }
}
and
public class LineVM
{
public int Id { get; set; }
public string Text {get; set;}
}
and you want to be able to edit all the "LineVM" within a "ParagraphVM". Then you would use an Editor Template so you would create a view at the following folder (if it doesn't exist) with the same name as the sub-model Views/Shared/EditorTemplates/LineVM.cshtml:
#model MyProject.Web.MVC.ViewModels.Paragraphs.LineVM
#{
//this will give you the List's element like Lines[index_number]
var field = ViewData.TemplateInfo.HtmlFieldPrefix;
}
<div id="#field">
#Html.EditorFor(l => l.Text)
</div>
Assuming you have a Controller's ActionResult that is returning a View and passing a ParagrapghVM viewmodel to a view, for example Views/Paragraph/_Paragraph.cshtml:
#model MyProject.Web.MVC.ViewModels.Paragraphs.ParagraphVM
#using (Html.BeginForm("Details", "Paragraphs", FormMethod.Post))
{
#Html.EditorFor(p => p.Lines)
}
This view would render as many editors for the list Lines as items contains that list.
So if, for example, the property list ParagraphVM.Lines contains 3 items it would render something like:
<div id="#Lines[0]">
<input id="Lines_0__Text name="Lines[0].Text"/>
</div>
<div id="#Lines[1]">
<input id="Lines_1__Text name="Lines[1].Text"/>
</div>
<div id="#Lines[2]">
<input id="Lines_2__Text name="Lines[2].Text"/>
</div>
With that you can know exactly what position each items is within the list and for example use some javascript to create a carousel or whatever you want to do with it. But remember that to edit that list you don't really need to know the position as Razor takes care of it for you. If you post back the model ParagraphVM, the list Lines will have the values bound (if any) without any additional work.
How about:
#using System
#using System.Text.RegularExpressions
var i = Convert.ToInt32(Regex.Matches(
ViewData.TemplateInfo.HtmlFieldPrefix,
#"\[([0-9]+)?\]")[0].Groups[1].ToString());
I think the easiest way is:
#Regex.Match(ViewData.TemplateInfo.HtmlFieldPrefix, #"(?!\[)\d+(?=\])")
Or as helper:
public static string Index(this HtmlHelper html)
{
Match m = Regex.Match(html.ViewData.TemplateInfo.HtmlFieldPrefix, #"(?!\[)\d+(?=\])");
return m.Success ? m.Value : null;
}
Inspired by #Jona and #Ryan Penfold
You can use #Html.NameFor(m => m.AnyField). That expression will output the full name property including the index. You could extract the index there...

How to display and edit fractions in an MVC/Razor View

I am trying to display and edit fractions in an MVC application. Previously in WPF I used the concept of a converter to take a double and format it as a fraction for the user and then take the users input and covert it back to a fraction. What would be the best way to do this in a Razor view?
I Admit it was harder than I thought. I'm still not sure if it's the best way to do it or not, but it works.
I defined a super simple Model:
public class MyModel
{
[DataType("Fraction")] //It's important to define DataType
public double MyDouble { get; set; }
}
and here is my simple controller:
public class HomeController : Controller
{
public ActionResult Index()
{
MyModel ViewModel = new MyModel { MyDouble = 0.06 };
return View(ViewModel);
}
[HttpPost]
public ActionResult Index(MyModel model)
{
// Update db.
// Do what you want to do.
return View(model);
}
}
Index view (\Views\Home\Index.cshtml):
#model MvcApplication1.Models.MyModel
#{ViewBag.Title = "Index";}
#Html.DisplayFor(m => m.MyDouble)
<br />
#using (Html.BeginForm("Index", "Home"))
{
#Html.EditorFor(m => m.MyDouble)
<input type="submit" value="Submit" />
}
<script type="text/javascript">
function fraction_changing(hiddenFieldId, numeratorId, denominatorId) {
var numeratorValue = document.getElementById(numeratorId).value;
var denominatorValue = document.getElementById(denominatorId).value;
var hiddenField = document.getElementById(hiddenFieldId);
hiddenField.value = numeratorValue / denominatorValue;
}
</script>
You will find out about the above Javascript code in just a minute.
Display Template is also so easy. I just used Fraction class (By Syed Mehroz Alam) to convert double values to Fraction.
As you know, Templates (which are Partial Views) should be placed in "DisplayTemplates" and "EditorTemplates" folders under "Views" folder. I prefer to put them in "Views\Shared\" so all other Views are able to use it.
Fraction.cshtml (\Views\Shared**DisplayTemplates\Fraction.cshtml**)
#using Mehroz // Fraction class lives in Mehroz namespace
#inherits System.Web.Mvc.WebViewPage<double>
#{
Fraction fraction = new Fraction(Model);
}
#fraction.Numerator / #fraction.Denominator
Let's now take a look at the tricky part, which is Edit Template.
So here is Fraction.cshtml (\Views\Shared**EditorTemplates\Fraction.cshtml**)
#using Mehroz
#inherits System.Web.Mvc.WebViewPage<double>
#{
Fraction fraction = new Fraction(Model);
string numeratorStr = fraction.Numerator.ToString();
string denominatorStr = fraction.Denominator.ToString();
string unifier = Guid.NewGuid().ToString().Replace('-', '_');
string hiddenFieldElementId = string.Format("hiddenField{0}", unifier);
string numeratorElementId = string.Format("numerator{0}", unifier);
string denominatorElementId = string.Format("denominator{0}", unifier);
string onchangingFunctionSyntax =
string.Format("fraction_changing('{0}', '{1}', '{2}')",
hiddenFieldElementId,
numeratorElementId,
denominatorElementId);
}
#Html.HiddenFor(m => m, new { id = hiddenFieldElementId })
#Html.TextBox("Numerator", numeratorStr,
new { id = numeratorElementId, onchange = onchangingFunctionSyntax }) /
#Html.TextBox("Denominator", denominatorStr,
new { id = denominatorElementId, onchange = onchangingFunctionSyntax })
What this template really do is:
Converting double value (its model) to an instance of Fraction.
Showing numerator and denominator value of the Fraction in separate Text Input.
Recalculate the double value (by Javascript)
Because Javascript code needs unique Id to get an element by document.getElementById(id), our Edit Template has to generate these unique IDs for related elements.
You can download the code here: http://sdrv.ms/MlyDI2
The best and cleanest way to solve your issue is to develop a Display/Edit Template.
Here is a nice article about it:
Overriding DisplayFor and EditorFor to create custom outputs for MVC

ASP.NET MVC Paging for a search form

I've read several different posts on paging w/ in MVC but none describe a scenario where I have something like a search form and then want to display the results of the search criteria (with paging) beneath the form once the user clicks submit.
My problem is that, the paging solution I'm using will create <a href="..."> links that will pass the desired page like so: http://mysite.com/search/2/ and while that's all fine and dandy, I don't have the results of the query being sent to the db in memory or anything so I need to query the DB again.
If the results are handled by the POST controller action for /Search and the first page of the data is rendered as such, how do I get the same results (based on the form criteria specified by the user) when the user clicks to move to page 2?
Some javascript voodoo? Leverage Session State? Make my GET controller action have the same variables expected by the search criteria (but optional), when the GET action is called, instantiate a FormCollection instance, populate it and pass it to the POST action method (there-by satisfying DRY)?
Can someone point me in the right direction for this scenario or provide examples that have been implemented in the past? Thanks!
My method is to have an Action that handles both the post and the get scenarios.
This is my which can be handled by both GET and POST methods:
public ViewResult Index([DefaultValue(1)] int page,
[DefaultValue(30)] int pageSize,
string search,
[DefaultValue(0)] int regionId,
[DefaultValue(0)] int eventTypeId,
DateTime? from,
DateTime? to)
{
var events = EventRepo.GetFilteredEvents(page, pageSize, search, regionId, eventTypeId, from, to);
var eventFilterForm = EventService.GetEventFilterForm(from, to);
var eventIndexModel = new EventIndexModel(events, eventFilterForm);
return View("Index", eventIndexModel);
}
The eventFilterForm is a presentation model that contains some IEnumerable<SelectListItem> properties for my search form.
The eventIndexModel is a presentation model that combines the eventFilterForm and the results of the search - events
The events is a special type of IPagedList. You can get more information and code for that here and here. The first link talks about IPagedList where as the second link has an Advanced Paging scenario which you should need.
The advanced paging has the following method that I use:
public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount, RouteValueDictionary valuesDictionary)
And I use it like so:
<%= Html.Pager(Model.Events.PageSize,
Model.Events.PageNumber,
Model.Events.TotalItemCount,
new
{
action = "index",
controller = "search",
search = ViewData.EvalWithModelState("Search"),
regionId = ViewData.EvalWithModelState("RegionId"),
eventTypeId = ViewData.EvalWithModelState("EventTypeId"),
from = ViewData.EvalDateWithModelState("From"),
to = ViewData.EvalDateWithModelState("To")
}) %>
This creates links that look like:
/event/search?regionId=4&eventTypeId=39&from=2009/09/01&to=2010/08/31&page=3
HTHs,
Charles
Ps. EvalWithModelState is below:
PPs. If you are going to put dates into get variables - I would recommend reading my blog post on it... :-)
/// <summary>
/// Will get the specified key from ViewData. It will first look in ModelState
/// and if it's not found in there, it'll call ViewData.Eval(string key)
/// </summary>
/// <param name="viewData">ViewDataDictionary object</param>
/// <param name="key">Key to search the dictionary</param>
/// <returns>Value in ModelState if it finds one or calls ViewData.Eval()</returns>
public static string EvalWithModelState(this ViewDataDictionary viewData, string key)
{
if (viewData.ModelState.ContainsKey(key))
return viewData.ModelState[key].Value.AttemptedValue;
return (viewData.Eval(key) != null) ? viewData.Eval(key).ToString() : string.Empty;
}
Make the Search parameter part of your View Model:
public SearchViewModel
{
string SearchParameters { get; set; }
List<SearchObjects> SearchResults { get;set; }
}
Then just set the Search Textbox equal to SearchParameters.
You cannot "store" the search query unless you bring back ALL results and then store those in the page somehow. That is horribly inefficient. The web is stateless, so you will have to go back to the database and re-query for more results.
I understand what you are saying; you could change the form to use buttons and post the page back everytime. Or, you could pass all the criteria in the URL for the paging as querystring variables. Or you could use JQuery to do the post (it has a $.post method that can be invoked from a link click or other click (http://api.jquery.com/jQuery.post/).
HTH.
This problem goes away if you include the search text, as well as the current results page, in your querystring instead of POSTing the search text. As an added benefit, your users can then bookmark their search results.
To do this your search button just needs to build the GET request URL using the current value of the search box. This can be done either in javascript or by using GET as your search form's method attribute, e.g. <form method="get" action="/search">.
I recommend cacheing your search results and giving them an ID. Then for each paging link, you can reference the search ID as a parameter (on each search page link) and in your action, pull it from cache, then query over it.
Using this method, you don't need to worry about anything other than the first POST submit of the search form.
Refer to my post for more details.
I had this same problem and here's what I did.
Download PagedList from Nuget
Change your form to do a GET and create a ViewModel type similiar to this (if you love AdventureWorks and Model Binding as much as I do):
`
using PagedList;
namespace SearchFormResultPagingExample.Models {
public class SearchViewModel {
public int? Page { get; set; }
public string EmailAddress { get; set; }
public string LastName { get; set; }
public IPagedList<Contact> SearchResults { get; set; }
public string SearchButton { get; set; }
}
}
`
3.Use the ViewModel as the parameter to your controller's action method
using System.Linq;
using System.Web.Mvc;
using SearchFormResultPagingExample.Models;
using PagedList; //NOTE: use Nuget to reference PagedList
namespace SearchFormResultPagingExample.Controllers {
public class SearchController : Controller {
const int RecordsPerPage = 25;
public ActionResult Index(SearchViewModel model) {
if (!string.IsNullOrEmpty(model.SearchButton) || model.Page.HasValue) {
var entities = new AdventureWorksEntities();
var results = entities.Contacts.Where(c => c.LastName.StartsWith(model.LastName) && c.EmailAddress.StartsWith(model.EmailAddress))
.OrderBy(o => o.LastName);
var pageIndex = model.Page ?? 0;
model.SearchResults = results.ToPagedList(pageIndex, 25);
}
return View(model);
}
}
}
Use the pager on in your View:
#model SearchFormResultPagingExample.Models.SearchViewModel
#using PagedList.Mvc;
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm("Index", "Search", FormMethod.Get)) {
#Html.ValidationSummary(false)
<fieldset>
<legend>Contact Search</legend>
<div class="editor-label">
#Html.LabelFor(model => model.EmailAddress)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmailAddress)
#Html.ValidationMessageFor(model => model.EmailAddress)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<p>
<input name="SearchButton" type="submit" value="Search" />
</p>
</fieldset>
}
#if (Model.SearchResults != null && Model.SearchResults.Count > 0) {
foreach (var result in Model.SearchResults) {
<hr />
<table width="100%">
<tr>
<td valign="top" width="*">
<div style="font-weight: bold; font-size:large;">#result.LastName, #result.FirstName</div>
#result.Title<br />
#result.Phone<br />
#result.EmailAddress
</td>
</tr>
</table>
}
<hr />
#Html.PagedListPager(Model.SearchResults,
page => Url.Action("Index", new RouteValueDictionary() {
{ "Page", page },
{ "EmailAddress", Model.EmailAddress },
{ "LastName", Model.LastName }
}),
PagedListRenderOptions.PageNumbersOnly)
}
MVC will coerce the querystring to and from your ViewModel type parameter. It's very slick!

Resources