Example of using AdditionalMetadata in MVC 3 - asp.net-mvc

In asp.net MVC 3 there is a new attribute that allows us to pass additional Meta Data to our views e.g.
[Required]
[AdditionalMetadata("Tooltip", "The title of the item")]
public string Title { get; set; }
The question is, how do I actually make use of this information in my view? I thought that perhaps it would render out the data as html 5 data attributes but this is not the case.
A simple example would be much appreciated.

According to the documentation:
You can use the
AdditionalMetadataAttribute class to
populate the
ModelMetadata.AdditionalValues
dictionary for a model property.
...
This metadata is made available to any
display or editor template when a
product view model is rendered. It is
up to you as application developer to
interpret the metadata information.
So let's make use of it in the view:
<h2>
#ModelMetadata.FromLambdaExpression(x => x.Title, ViewData).AdditionalValues["Tooltip"]
</h2>

example in a template:
Object optionlabelOverride;
ViewData.ModelMetadata.AdditionalValues.TryGetValue("OptionLabelText", out optionLabelOverride);
the variable you are reading must be an object and then you can cast it. Everything you set in the model is available as ViewData.

Related

Confused about Usage of LabelFor() html helper in MVC 2.0

I am working on an MVC 2.0 C# web Applciation. In one of my form, i am using LabelFor() html helper.
I am using the following syntax:
<%=Html.LabelFor(model=>model.Addedon)%>
Here, for this label i would like to associate a initial value that is DateTime.Now
I tried some thing like this:
<%=Html.LabelFor(model=>model.Addedon,new{value=DateTime.Now})%>
But, i am getting an error saying that there is no over load for this helper taking two arguments.Please help
UPDATED:
The form is create form/ add form which makes an insert operation. So, i am building a model and updating that model to the database.
In that model, i have a field called createdby. So, i need to associate this value with the username logged in and doing the insert operation.
So, how to associate this username value with the model field and i need to display as label so that it will be read only field.
Hope this makes clear..
LabelFor is only for, you guessed it, rendering a <label> element.
It also uses the [Display] and [DisplayName] attributes, so you can have a strongly-typed label with custom name.
What you're after is probably this:
<div>
<%= Html.LabelFor(model => model.Addeon) %>
</div>
<div>
<%= Html.DisplayFor(model => model.Addeon) %>
</div>
So the LabelFor will generate the property name description (e.g. 'Addeon'), while the DisplayFor will render the property value. DisplayFor can use the [DisplayFormat] attribute if you need custom formatting. You can set the default property value in the view model's constructor:
public class ViewModel
{
[Display(Name = "My awesome date")]
public DateTime Addeon {get;set;}
public ViewModel()
{
Addeon = DateTime.Now;
}
}
[EDIT]
Actually, your edit would make for a good second question instead of putting it here. Anyway, in your situation I'd create a dedicated view model that would hold the properties you need (e.g. user name) and would be filled in controller. Everything else would be conceptually the same - view would bind to the view model.

Will Razor's EditorFor() syntactic sugar create a checkbox list in the View?

I've been jumping through hoops to add an array of checkboxes to a View in an asp.net MVC project (using a custom jQuery plugin), but just realized it might be possible using the "in-the-box" functionality of the MVC / Razor extravaganza.
Theoretically, the following should work:
If a model has an array of bool, such as:
public bool[] chicagoBoolsFools { get; set; }
...calling this in the View:
#Html.EditorFor( model => model.chicagoBoolsFools)
...should create an array of checkboxes bound to the Model member.
Is this the case only in theory, or also in actuality?
Unfortunately #Html.EditorFor doesn't even create checkboxes... Maybe I am misunderstanding you but I would try something more along the lines of this post.
Try stuffing a model with either a list of Checkboxes (represented by a string and a boolean value) or just a basic string property for each checkbox, which can then be rendered in the view using several #Html.CheckBoxFor calls.
#Html.CheckBox or #Html.CheckBoxFor are key here.

How to use DisplayForModel() to show a list of Customers?

Normally we use DisplayForModel or EditorForModel to display and edit a single Customer object, respectively.
How to display a list of Customers using these templating scheme?
Assuming you have a collection of customers in your view model
public class MyViewModel
{
public IEnumerable<Customer> Customers { get; set; }
}
you could use the following in your view:
#Html.DisplayFor(x => x.Customers)
and then in the editor/display template (~/Views/Home/DisplayTemplates/Customer.cshtml or ~/Views/Shared/DisplayTemplates/Customer.cshtml):
#model AppName.Model.Customer
<div>#Model.Name</div>
The Customer partial will be then rendered for each element of the customers collection of your main model. The important thing is the naming convention: the partial should be situated in a DisplayTemplates subfolder and called the same as the collection type (Customer).
How about following Haack's tutorial ?
As great as this feature is, there is
one template that’s conspicuously
missing. ASP.NET MVC does not include
a template for displaying a list of
objects in a tabular format.
Earlier
today, ScottGu forwarded an email from
Daniel Manes (what?! no blog! ;) with
a question on how to accomplish this.
Daniel had much of it implemented, but
was trying to get over the last
hurdle. With Brad’s help, I was able
to give him a boost over that hurdle.
Let’s walk through the scenario.

Passing model data to asp.net mvc EditorTemplates

ScottGu in this post link text shows how one can utilize EditorTemplates for things such as a Country DropDownList. My question is how can one pass a dynamic list of Countries to the EditorTemplate?
Even better you make the partial view strongly typed and pass the model to the EditorFor helper
#Html.EditorFor(m=>m.SelectedCountry, Model.AvailableCountries)
Probably the most elegant solution is using a Custom Attribute, you can later access Model metadata using: ViewData.ModelMetadata.
e.g:
[Foreign(Type="DropDown", TableName="Countries")]
public int IdCountry { get; set; }
where ForeignAttribute is a class you must declare, and later use it to build your editor template.
You can pass it in ViewData and feed ViewData from and ActionFilter if the data is required very often (although arguable it is an anti-pattern).
Similar to #Benja's answer
You can also use the [AdditionaMetaData(key,value)] attribute in a similar fashion without having to define your own attribute. Key and value have to be strings.
The extra data can be retrieved in the view with: #ViewData.ModelMetadata.AdditionalValues["DropDownData"]

Function in ASP.NET MVC

A function returns only one view.
what if I want to return multiple views in a function?
For example, I have this code:
Function Index() As ActionResult
Dim _news As DataTable = News.newsSelect()
Dim _announcement As DataTable = Announcement.SelectAnnouncement()
Return View()
End Function
I want to return _news and _announcement to be used in the aspx page. How would I do this?
Are you trying to show both sets at the same time? News and Announcements?
If so then why not implement either a PartialView or two PartialViews?
Then in your main view you can render them and pass the collection to the PartialViews?
There are heaps of samples on this and the one I recommend is in NerdDinner if you haven't already seen it.
I hope this helps. If you want sample code then let me know.
One simple way is just to have those two datasets sent in a ViewData element, which you can access in a field.
example:
ViewData["Elements"] = new SelectList(aElements, "Guid", "Name");
is consumed as:
<%= Html.DropDownList("Elements","Pick an element")%>
Also, I think that if you read between the lines of this blog post here you will find an elegant way of achieving what you want ;) but its a bit more involved..(only because you mentioned Views instead of just variables..
Quote:
We need to create our own implementation of IViewFactory. This
is responsible for locating and
creating an instance of an IView
(which both ViewPage and
ViewUserControl implement).
To “inject” (all you DI fans excuse me borrowing the term without
using a DI framework) our new View
Factory into every Controller we are
going to create our own
IControllerFactory implementation.
We need to configure the framework to use our new Controller
Factory.
Finally we can create two Views – an AJAX version and a pure
HTML version.
Building on that should be all you need
Good luck!
Ric
Assuming what you are trying to do is use both of those DataTables to populate some View, then my recommendation would be to create a wrapper object and then a strongly typed view based on this object.
The wrapper object would contain properties for all of the data elements that you need in order to render your view properly. In your case, it is 2 DataTable objects. I do not really know VB, so all my examples will be in C#. Here is an example of the data wrapper class...
public class IndexViewData
{
public DataTable News { get; set; }
public DataTable Announcement { get; set; }
}
You then might update the Index action in your controller as follows:
public ActionResult Index()
{
var viewData = new IndexViewData();
viewData.News = News.newsSelect();
viewData.Announcement = Announcement.SelectAnouncement();
return View(viewData);
}
Finally, you would need to create/update your view to be strongly typed. This is done by having your page inherit from the generic System.Web.Mvc.ViewPage<T> class. Just substitute the view data wrapper created earlier for T. To do this, you would set the inherits attribute of the <%# Page %> element. In your case, if we assume your root namespace is called "Foo", you might have the following page declaration in your Index.aspx view (added extra line breaks for readability):
<%# Page Title=""
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<Foo.Models.MyModelType.IndexViewData>"
%>
Once you have a strongly typed view for your view data wrapper, you can access the wrapper object in your view using the Model property. Here is an example of something you could do in your Index.aspx view
<%-- Output some random data (bad example, for demonstration only) --%>
<%= Model.News[0]["title"] %><br/>
<%= Model.Anouncement[0]["body"] %>
In reality you're probably going to do something like iterate over each row of the data table. Regardless, once you create the strongly typed view, your model object, which was passed to the view in the Index method of the controller, is available in the Model property within the view.
You can find detailed tutorials at the ASP.NET MVC site

Resources