Add property to an ASP.NET MVC 2 ViewUserControl - asp.net-mvc

I have created a ViewUserControl in my ASP.NET MVC 2 project. This ViewUserControl serves as the general page-header for all views in the project.
How can I add a custom property on ViewUserControls, accessible from views using that control?..:
<%# Register
Src="../Shared/Header.ascx"
TagName="Header"
TagPrefix="uc" %>
<uc:Header
runat="server"
ID="ucHeader"
MenuItemHighlighted="Menuitem.FrontPage" /> <!-- custom property, here -->

Instead of creating user controls ala WebForms way I would suggest you the following:
Create a strongly typed user control Header.ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<div><%: Model %></div>
And then simply include it in your pages:
<% Html.RenderPartial("~/Views/Shared/Header.ascx", "some value"); %>
In my example the user control is strongly typed to string but you could've used any custom type.

Related

ASP.NET MVC - Html.RenderPartial issues

I have a usercontrol named "LoginUserControl.ascx" which I have placed in a master page.
Header of "LoginUserControl.ascx"
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MultiTechnologyWeb.Models.loginmodel>" %>
Then I used the below code to show the usercontrol in the masterpage.
<% Html.RenderPartial("LoginUserControl"); %>
On first run the page "index" is loaded.
Notice the header of the "index" page, no model is specified. Thus page load successfully
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MT.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
Now I click on the link to open register.aspx. I got the below error
The model item passed into the dictionary is of type 'MultiTechnologyWeb.Models.registermodel', but this dictionary requires a model item of type 'MultiTechnologyWeb.Models.loginmodel'.
Header of "register.aspx" page
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MT.Master" Inherits="System.Web.Mvc.ViewPage<MultiTechnologyWeb.Models.registermodel>" %>
So to my understanding model is being interchanged, so anybody can please help me on how to resolve this issue
More Explanation.............LATEST
I have debug, i know that the crash is occuring after the actionresult for register is finished execution.
Code below is for actionresult "register"
public ActionResult register()
{
registermodel model;
//some code here
return View("register",model);
}
So i'm just returning one type of model that is "registermodel", Would it be possible to return another model such as "loginmodel" by using a list or array to return multiple models in the same view.
You should use <% Html.RenderAction("Logon","Account"); %> in your MasterPage instead of using RenderPartial and in this action you just return the login partial you want to use in the header
public ActionResult Logon(){
// do your stuff
return PartialView("LoginUserControl");
}
By this way you could pass the loginmodel to the LogInPartial and pass registermodel to the register page
Please not that RenderAction and RenderPartial are not the same.
RenderPartial will render only the view. While RenderAction will make a new MVC roundtrip, by making a new instance of the controller etc and returning the result.
To solve your issue you could pass in the MultiTechnologyWeb.Models.loginmodel where you call <% Html.RenderPartial("LoginUserControl"); %>. It would look like this:
<% Html.RenderPartial("LoginUserControl", new MultiTechnologyWeb.Models.loginmodel()); %>
Or:
<% Html.RenderPartial("LoginUserControl", Model.LoginModel); %>
If you're not wanting to send a model to your partial view, which I've wanted to do in the past, you do have to at least pass something to the RenderPartial method.
This was the only method I could find that allowed me to now have to pass a model. I tried passing null and it continued to pass the parent model
<% Html.RenderPartial("LoginUserControl", new ViewDataDictionary()); %>

What is strongly-typed View in ASP.NET MVC

What is strongly-typed View in ASP.NET MVC?
It is an aspx page that derives from System.Web.Mvc.ViewPage<TModel>. It is said that this view is strongly typed to the type TModel. As a consequence to this there's a Model property inside this view which is of type TModel and allows you to directly access properties of the model like this:
<%= Model.Name %>
<%= Model.Age %>
where as if your aspx page derived from System.Web.Mvc.ViewPage you would need to pull values from ViewData the view no longer knows about the TModel type:
<%= (string)ViewData["Name"] %>
<%= (int)ViewData["Age"] %>
or even worse:
<%= ((SomeModelType)ViewData["model"]).Name %>
and there's no compile time safety in such code.
Notice also that there's the ViewUserControl<TModel> counterpart for strongly typed partials (ASCX).
Strongly typed views are used for rendering specific types of model objects, instead of using the general ViewData structure. By specifying the type of data, you get access to IntelliSense for the model class.
It's a view which specifies the type of the object passed to it as its model - so instead of a view that inherits from ViewPage, it inherits from ViewPage<T> where T is the type of the model.

How to format a date in a view for two-way binding in MVC 2?

So let's say I have a view that access a date:
<%= Html.TextBoxFor(model => Model.Birthday) %>
How do I have my view dictate how that date is formatted? I'd like to use common formatting options, and it's important that this is 2-way (both for display and data-entry).
In your model, you could use System.ComponentModel.DataAnnotations metadata to specify the format you want the property in. e.g.
[DisplayFormat(DataFormatString="{0:MM/dd/yyyy}")]
public DateTime Birthday { get; set; }
Then, in your view, use:
<%= Html.EditorFor(model => model.Birthday) %>
Unfortunately, the regular HTML Helpers don't respect the metadata, so you have to use Html.EditorFor.
Use a specific ViewModel class that has a string in the format you want for the birthday and use that to display in the textbox. When you post the form, if you are using default binding for the domain object itself, it should parse the string for you. If you are using a ViewModel, you'll have to parse it upon posting the form.
I was kind of surprised to see that you can't just throw a format string in Html.EditorFor(). I've sinced starting using EditorTemplates.
Create a directory structure in your solution.
Views > Shared > EditorTemplates
Add a new MVC 2 User Control in the EditorTemplates folder and name it DateTime.ascx. Html.EditorFor(DateTime) will now use this user control for display.
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DateTime?>" %>
<%= Html.TextBox(string.Empty, (Model.HasValue ? Model.Value.ToShortDateString() : string.Empty)) %>

How do I create a strongly typed view page using ASP.NET MVC VB.NET XML Literals View Engine?

I am using the ASP.NET MVC VB.NET XML Literals View Engine created by Dmitry Robsman and described on his blog in this post.
http://blogs.msdn.com/dmitryr/archive/2008/12/29/asp-net-mvc-view-engine-using-vb-net-xml-literals.aspx
I would like to create strongly typed view pages using this view engine, but it doesn't seem to contain the requisite VbView(Of TModel) generic type by which I would create such a view class.
The end result should look something like this:
Namespace Views.Client
Public Class Details(Of Models.Client)
Inherits SiteMaster
Public Overrides Function RenderContent() As XElement
Return _
<fieldset>
<legend>Fields</legend>
<p>
FirstName:
<%= Xhtml.Encode(Model.FirstName) %>
</p>
<p>
MiddleName:
<%= Xhtml.Encode(Model.MiddleName) %>
</p>
<p>
LastName:
<%= Xhtml.Encode(Model.LastName) %>
</p>
<fieldset>
End Function
End Class
End Namespace
Once there is a VbView(Of TModel) class that inherits from Dmitry's VbView class, I will need help figuring out how to hook that up so that it works with standard MVC controllers that call the view like this.
Function Details(ByVal id As Integer) As ActionResult
Dim c = SomeGetClientFunction(id)
Return View(c)
End Function
I downloaded the ASP.NET MVC C# source code and was able to figure out how to create the VbView(Of TModel) class by mirroring some of that structure. I have created a project on CodePlex that contains that new class and a couple other changes that enhance what Dmitry did. http://vbmvc.codeplex.com

Trying to pass Model down to partial, how do I do this?

My action creates a strongly typed viewdata, which is passed to my view.
In the view, I pass the Model to the render partial method.
public ActionResult Index()
{
ViewDataForIndex vd = new ViewDataForIndex();
vd.Users = Users.GetAll();
return View(vd);
}
public class ViewDataForIndex: ViewData
{
public IList<User> Users {get;set;}
}
now in the view:
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ViewDataForIndex>" %>
<% Html.RenderPartial("~/controls/blah.ascx", ViewData.Model); %>
and in blah.ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
how do I access my model now?
if I wanted to create a strongly typed class for my ViewUserControl, how would I do that? inherit from?
One: Inside the ascx:
<%= Model.YourProperty %>
Two: Provide a type Argument to ViewUserControl:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<String>" %>
I like #jfar's second approach better as it allows for easier modification if you ever decide to pass a more complex model to the view.
So you may pass a class that has multiple properties and/or more child objects.
If you inherit from the object now, then all you need to do is to inherit from your complex object and change one piece of code, as well as add the new properties, and your done.
More specifically to jfar's answer:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ViewDataForIndex>" %>
If your parent page has a model of type ViewDataForIndex, calling the child with the same ViewData.Model will also pass an object of type ViewDataForIndex.

Resources