How to use Model data in a view ASP MVC? - c#

I'm a beginner with ASP MVC and I'm trying to show data from a model in a view.
This is how I display the data :
#Html.DisplayFor(modelItem => item.Budget_Year)
But I don't know how to use this data, for example I tried to round up this result and I tried naively :
#{
double test = (modelItem => item.Budget_Year);
test = System.Math.Round(test , 2);
}
But I can't use it like that : Cannot convert lambda expression to type 'double' because it is not a delegate type
Someone can explain me how to use this different items from my model in my view ?
Best regards,
Alex

you have many ways to do this more properly :
use a ViewModel class, where you have a property which is your Rounded value
public class MyViewModel {
public double BudgetYear {get;set;}
public double RoundedBudgetYear {get {return Math.Round(BudgetYear, 2);}}
}
and in View
#Html.DisplayFor(m => m.RoundedBudgetYear)
or
Add a DisplayFormat attribute on your property
see Html.DisplayFor decimal format?
or
Create your own HtmlHelper, which will round the displayed value.
#Html.DisplayRoundedFor(m => m.BudgetYear)

First you need to declare what model you will actually be using and then use it as Model variable.
#model YourModelName
#{
var test = Model.BudgetYear.ToString("0.00");
}

If you're just trying to access a property of the model you can do it like this:
double test = Model.BudgetYear;
The lambda is only necessary if you're trying to have the user assign a value to it from the view.

I wouldn't do this in the view. Instead I would round BudgetYear in your model / view model and send it down to the View already rounded. Keep the logic in the controller / model and out of the view. This will make it easier to test as well

Related

use string in view

I have this in my controller:
string PONumber = Request.QueryString["PONumber"];
return View();
My question is how would I use the string in my view ?
I have tried:
#{
ViewBag.PONumber
}
but I get this error:
This operation will be resolved at runtime. Am I not doing this right ?
I have also tried:
<%= PONumber %>
and that also did not work
You need to put the result from your querystring into the ViewBag before you can pull it out of the ViewBag in your view:
// Assign directly to ViewBag
ViewBag.PONumber = Request.QueryString["PONumber"];
return View();
In your view, don't try to print the value by writing it in a code block (#{ }); simply use it where you'd like:
<h2>The PO Number is #ViewBag.PONumber.</h2>
You have a misnomer, when you have a Controller with:
[HttpGet]
public ActionResult GetExample(string PONumber)
{
}
The PONumber parameter, would represent said equivalent for your Query String. So you honestly wouldn't need to manually call Request.QueryString[...].
So you would assign parameter, directly to your ViewBag. However, you could add it directly to a model and display through your model also.
If your wanting to use a ViewBag, you would simply do:
// Front End:
#ViewBag.PONumber
// Back End:
ViewBag.PONumber = PONumber;
Also, make sure when you request your data that it isn't actually a null or empty value.
ViewBag.PONumber = Request.QueryString["PONumber"];
return View();
and then in view
#ViewBag.PONumber

Is it possible to know a variable's name [duplicate]

This question already has answers here:
How can I get the name of a variable passed into a function?
(23 answers)
Closed 8 years ago.
One thing to note is: I need to get the variable's name, not the property's name.
I have a scenario where I need to pass in either List<int> or List<double> to a view. So in the partial view I bind the model to dynamic:
#model dynamic
var nameOfParameter = Web.Controllers.MemberInfoGetting.GetMemberName(() => Model);
#foreach (var value in list)
{
<td>#Html.Editor(value, "DoubleTemplate", new { Column = count, Switcher = (YearOfProgram >= count)})</td>
sum += (double)value;
++count;
}
And this is how I call the partial view from the main view:
#Html.Partial("_myPartial", Model.CategoryList)
Then I found that I have to know the name(CategoryList) of the list which is passed into the partial view.
Here I found many posts talking about using something like this:
public static class MemberInfoGetting
{
public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
{
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
return expressionBody.Member.Name;
}
}
}
This code doesn't work for me as the result of (nameOfParameter )calling it will always be "Model", rather than "CategoryList".
So, is it possible to achieve what I want?
Update1
The reason why I need to pass in the name of the list is because I need the name of the list to form the name on the html element into something like: CategoryList_1. So Razor knows I am trying to bind the value of the textbox into the 1st element of a property in my view model.
class MyViewModel
{
................
public List<double> CategoryList {get; set;}
................
}
Update2
#Html.RenderPartial("_VerificationSummarySection",new { ListName = "PracticeEvaluationCreditsVerifiedList", List = Model.PracticeEvaluationCreditsVerifiedList})
I'm now trying to pass in the name of the list by using RenderPartial. But, I cannot find the right way to use it.
Names are relative. The list itself doesn't have a name.
One thing to notice is : I need to get the variable's name, not the property's name.
In your use of the method:
var nameOfParameter = Web.Controllers.MemberInfoGetting.GetMemberName(() => Model);
The name here is Model, and Model is the property; it isn't a variable. You have obtained the name of the property: "Model". You cannot, however, obtain the name as it would have been in a calling context (even in regular C# this is hard; between views, however, it is essentially impossible).
As an aside, with that GetMemberName method, if you did use it to obtain the name of a variable, in IL terms it would actually cease being a variable, and would instead become a field - because that is how "captured variables" are implemented by the compiler.
You should instead make it possible to pass down the name you want; either as additional context on the view, or as a view-model that encapsulates a list and a name, or by creating a "named list" concept (perhaps by subclassing List<T> or similar, or by adding an INamedList interface).

How do I pass a property expression back to the controller?

I have a view that displays a table of data that I want to be able to sort by specifying a property on the row type.
My model (so far) is:
class Model
{
List<DataType> data;
Expression<Func<DataType, object>> SortProperty;
}
I've tried creating that in the view to be passed into my controller as follows:
<a href='<%= Url.Action("Index", "Approvals", new IndexModel() { Page = Model.Page, SortProperty = ((ApprovalModel m) => m.Id)}) %>'>Id</a>
which renders as:
<a href='/PartsLegislation/Approvals.aspx/Approvals?SortProperty=m%20%3D%3E%20Convert(m.Id)'>Id</a>
so it sort of looks like it'll work (all-be-it with a Convert expression in there), however in the controller SortProperty is always null.
TL;DR: How can I pass an expression pointing to a property from my view to the controller?
Edit: My controller action is as below:
[HttpGet]
public ActionResult Index(Model viewModel)
{
....
viewModel.Approvals = PartsDC.Repository<Approval>()
.Where(a => !a.Deleted)
.OrderBy(viewModel.SortExpression)
.Skip((viewModel.Page ?? 0) * RowsPerPage)
.Take(RowsPerPage)
.Select(a => Mapper.Map<Approval, ApprovalHeaderModel>(a))
.ToList();
...
}
As far as I know you can't pass complex objects via URL. You can pass for example string with name of property.
However if you want to just sort table maybe you should think about another approach to this problem. Check this http://www.kryogenix.org/code/browser/sorttable/ .
It allows you to simply sort your table by clicking on headers.

Displaying results of a Stored Procedure in MVC View (EF 5 / MVC 4)

The goal
I want to display in my view the results of stored procedure.
The problem
Entity Framework automatically imported for me a method that executes a procedure, however I'm not getting the results I expect displaying on the screen.
The imported function is:
public virtual ObjectResult<getProductsListForHome_Result> getProductsListForHome(Nullable<int> inOffer, Nullable<int> categoryId)
{
var inOfferParameter = inOffer.HasValue ?
new ObjectParameter("inOffer", inOffer) :
new ObjectParameter("inOffer", typeof(int));
var categoryIdParameter = categoryId.HasValue ?
new ObjectParameter("categoryId", categoryId) :
new ObjectParameter("categoryId", typeof(int));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<getProductsListForHome_Result>("getProductsListForHome", inOfferParameter, categoryIdParameter);
}
What I have already tried
On ProductsController:
//
// GET: /Products/
public ActionResult Index()
{
ObjectResult<getProductsListForHome_Result> products = db.getProductsListForHome(1, 14);
return View(products.ToList());
}
Using the previous code, when I access http://myapp.com/Products/ I'm getting the following message:
The model item passed into the dictionary is of type
'System.Collections.Generic.List1[MyApp.Models.getProductsListForHome_Result]',
but this dictionary requires a model item of type
'System.Collections.Generic.IEnumerable1[MyApp.Models.bm_products]'.
What do I have to do to resolve this?
First, well-written question!
This is a type-casting problem, and it looks like your answer is the accepted answer here:
MVC: The model item passed into the dictionary is of type X, but this dictionary requires a model item of type X
Most likely your View is a strongly typed one, and it is declared as
#model System.Collections.Generic.IEnumerable<MyApp.Models.bm_products>
However you are passing it a different type in controller, and experiencing the error.
What you can do:
Specify another type for the View. View itself might require some refactoring after this:
#model System.Collections.Generic.IEnumerable<MyApp.Models.getProductsListForHome_Result>
Preferable. Run some code in controller to convert collection returned from SP into something View can consume:
public ActionResult Index()
{
ObjectResult<getProductsListForHome_Result> products = db.getProductsListForHome(1, 14);
List<bm_products> viewProducts = products.Select(p => new bm_products{ProductName = p.Name, ProductPrice = p.Price}).ToList();
return View(viewProducts);
}

Bind model during post of form inside EditorTemplate (on array)/multiple bind prefixes?

I have a complex Model containing an array. For rendering items for this array I'm using EditorFor like this:
for (int i = 0; i < Model.Contacts.Phones.Length; i++)
{
#Html.EditorFor(x => x.Contacts.Phones[i])
}
Inside editor there is a post-form. Problem is, that binding is successful only when I exactly specify binding prefix:
[HttpPost]
public ActionResult SavePhone(
[Bind(Prefix = "Contacts.Phones[0]")]Contact5UsedPhone model)
{ ... }
So it works only for first of the elements. What is the correct form of prefix?
For the more there is also on the same page editor for different property - but same type of model and same action is therefore executed. Is it possible to set more than one binding prefix? E.g.
[HttpPost]
public ActionResult SavePhone(
[Bind(Prefix = "Contacts.Phones[0], Contacts.AnotherPrefix")]
Contact5UsedPhone model)
{ ... }
Thank you!
edit - model:
public class ContactsViewModel
{
public Contact5UsedPhone AddiblePhone {get;set;}
public Contact5UsedPhone[] Phones {get;set;}
...
}
edit - answer:
I found a solution for this. As there is one array (Phones) and one single entity (AddiblePhone), I used two parameters and simple if:
[HttpPost]
public ActionResult SavePhone(
[Bind(Prefix = "Contacts.Phones")]Contact5UsedPhone[] models,
[Bind(Prefix = "Contacts.AddiblePhone")]Contact5UsedPhone model)
{
model = model ?? models[0];
...
}
The question still remains - what if there were AddiblePhones as array? Is it possible to use two prefixes for one parameter, or does it have to be divided to two parameters as I did in this case?
it's nice that u have found a clear solution. Maybe you will like a clearer one. Have a look at
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
http://zahidadeel.blogspot.com/2011/05/master-detail-form-in-aspnet-mvc-3-ii.html
http://ivanz.com/2011/06/16/editing-variable-length-reorderable-collections-in-asp-net-mvc-part-1/
We found clear and simple answer for this:
#Html.EditorFor(x => x.Phones[i],
"~/Views/Contacts/EditorTemplates/Contact5UsedPhone.cshtml",
"")
The last "" means it won't use any prefix for binding. That's great, so you don't need any binding prefix and two kinds of accepted modes as showed in answer in the question.
A little question still remains - what if there were AddiblePhones as array? Is it possible to use two prefixes for one parameter, or does it have to be divided as I proposed in answer in question? But probably this signals bad design if something like that is needed...
EDIT (Telerik controls):
Problem of this nice solution appears when using Telerik dropdown list, as it generates not unique ids for elements and these controls are jQuery controlled, therefore it doesn't work properly.
WARNING:
I found out, that when using Bind attribute you CANNOT use " " (space) between attribute and type of parameter.
works:
[Bind(Prefix = "Phones")]Contact5UsedPhone[]
doesn't work:
[Bind(Prefix = "Phones")] Contact5UsedPhone[]
I don't know if this is only case of arrays. But it seems wird to me.

Categories