Using Html.RenderPartial() in ascx files - asp.net-mvc

I'm trying to use Html.RenderPartial in acsx file
and I'm getting an error:
Compiler Error Message: CS1973: 'System.Web.Mvc.HtmlHelper'
has no applicable method named 'RenderPartial' but appears to have an
extension method by that name. Extension methods cannot be dynamically
dispatched. Consider casting the dynamic arguments or calling the
extension method without the extension method syntax
<a href="/projects/<%=project.Id %>">
<% Html.Label("fdf"); %>
<% Html.RenderPartial("ProjectName", Model.Id); %></a></li>
<%} %>
However I've import neccessary namespaces, so it won't be error at
<% Html.Label("fdf"); %>
Are there any methods to use Html.RenderPartial in ascx file?

The compiler cannot choose the correct method because your Model is dynamic. Change the call to:
<% Html.RenderPartial("ProjectName", (int)(Model.Id)); %>
Or any other datatype Id is.

In case anyone else made the same mistake I did:
#Model MyViewModel
This will treat your model as dynamic
#model MyViewModel
This is a correctly strongly typed view. Note the lack of capitalisation!
Note, that this is Razor, unlike the original question.

The only way i found to pass eg. an IEnumerable was to create a local variable and pass in this one.
For Example
#{
IEnumerable<Demo.Models.Friend> friends = Model.Friends;
Html.RenderPartial("_FriendsList", friends);
}
Html.RenderPartial("_FriendsList", (IEnumerable<Demo.Models.Friends>)(Model.Friends)); did not work!

Related

How to pass action name from controller to view

I am new to razor and I need help to pass the action name from controller to view using ViewBag. Following is my code:
public ActionResult Index(int id = 0)
{
ViewBag.MasterId = id;
ViewBag.ActionName = "ApplicationProcess";
return View();
}
From the above action method I am passing action name of that is being used in view that is render in result of this function.
<body>
<h2>Index</h2>
<div style="width: 1100px;">
<div style="float: left; width: 400px;">
#{Html.RenderAction("MasterRecordProcess", "Process");}
</div>
<div style="float: right">
#{Html.RenderAction("MasterRecordBasicInfo", "Process", new { id = ViewBag.MasterId });}
</div>
<div style="float:right;margin-top:50px;" class="task-div">
#{Html.RenderAction(#ViewBag.ActionName, "Process", null);}
</div>
</div>
</body>
Now in above view I want to use the ViewBag.ActionName passed from controller in Html.RenderAction but this is giving me error message.
Compilation Error
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1973: 'System.Web.Mvc.HtmlHelper<OAC.Areas.Personal.Models.MasterModel>' has no applicable method named 'RenderAction' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
Kindly help how can I render the action name passed from controller in viewBag object. Thank you.
As #Stephen mentioned you must first cast the view bag content:
#{
var actionName= (string)ViewBag.ActionName;
}
Then you can use it:
#{Html.RenderAction(actionName, "Process", null);}
The error itself says that "consider casting the dynamic arguments or calling the extension method without the extension method syntax."
C# does not support calling an extension method (Html.RenderAction()) when any of the arguments is of a dynamic type. You have to either call the extension method statically or cast the argument to a non-dynamic type.
In this case you can the ViewBag to a String and use

ASP.NET MVC: Accessing ViewModel Attributes on the view

Is there any way to access any attributes (be it data annotation attributes, validation attributes or custom attributes) on ViewModel properties from the view? One of the things I would like to add a little required indicator next to fields whose property has a [Required] attribute.
For example if my ViewModel looked like this:
public class MyViewModel
{
[Required]
public int MyRequiredField { get; set; }
}
I would want to do something in the EditorFor template like so:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<int?>" %>
<div class="label-container">
<%: Html.Label("") %>
<% if (PROPERTY_HAS_REQUIRED_ATTRIBUTE) { %>
<span class="required">*</span>
<% } %>
</div>
<div class="field-container">
<%: Html.TextBox("") %>
<%: Html.ValidationMessage("") %>
</div>
The information you're looking for is in ViewData.ModelMetadata. Brad Wilson's blog post series on Templates should explain it all, especially the post on ModelMetadata.
As far as the other ValidationAttributes go, you can access them via the ModelMetadata.GetValidators() method.
ModelMetadata.IsRequired will tell you if a complex type (or value type wrapped in Nullable<T>) is required by a RequiredAttribute, but it will give you false positives for value types that are not nullable (because they are implicitly required). You can work around this with the following:
bool isReallyRequired = metadata.IsRequired
&& (!metadata.ModelType.IsValueType || metadata.IsNullableValueType);
Note: You need to use !metadata.ModelType.IsValueType instead of model.IsComplexType, because ModelMetadata.IsComplexType returns false for MVC does not consider to be a complex type, which includes strings.
I would suggest not doing that way because you're adding logic in the view which is a bad practice.
Why don't you create a HtmlHelper or LabelExtension, you can call ModelMetaProvider inside the method and find out whether the property has Required attribute decorated?

Nested EditorFor/DisplayFor override field name

Short of overriding ViewData.TemplateInfo.HtmlFieldPrefix with an empty string, is there a way to keep the prefix from coming through on a nested set of strongly-typed EditorFor or DisplayFor helper calls?
Here's the ugly markup/code I have working so far:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.Web.Mvc.SelectList>" %>
<% ViewData.TemplateInfo.HtmlFieldPrefix = ""; %>
<%=Html.DropDownList("sort", Model)%>
I've tried the *For overload that allows specifying htmlFieldName but that only changes the immediate level. If I have a prefix at the point of that call, I just change what is appended to the prefix.
I could write the template markup by hand, but doing so for a SelectList object seems like I will just end up copying over the MVC source with a single tweak since it involves object data binding logic.
If you have a property on your view model, rather than just doing dropdown list directly on the model, you can put a DataAnnontation attribute on it.
public class MyModel
{
[Display(Name="Your Favorite Choices")]
public string[] Choices {get; set;}
}
then in your code
<%= Html.LableFor(m => m.Choices) %><br />
<%=Html.DropDownList("sort", Model.Choices)%>
Should use that name.
[Hope I got it right from memory. :)]
Here's the MSDN link:
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayattribute.displayattribute.aspx
Not sure if I understand your question, but, if you render the "child" views as partials instead of EditorFor then the fields will not be prefixed.

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.

Why do Strongly Typed Html Helpers help me?

I read ScottGu's explanation on Strongly Typed Html Helpers and I understand that it gives me the ability to do better compile time checking of views. I was under the impression that I already had this when I used the model.PropertyName in the MVC1 Html.TextBox helper, but apparently that is not true. So, how does using a lambda expression do this better for me?
Consider the syntax of the existing HTML helper methods:
<%= Html.TextBox("Quantity", Model.Quantity) %>
If you rename the Quantity property on your object to "CurrentQuantity", the generated <input> element will still have name="Quantity" specified, and model binding will break if you don't remember to change that first parameter.
By using a lambda expression to specify the name of the element, an incorrect or misspelled property name becomes a compilation error.
<!-- No magic strings here! -->
<%= Html.TextBoxFor(model => model.CurrentQuantity) %>
The improvement comes when you specify the name of the property to the helper. With strongly typed helpers, it uses the lambda expression instead of the property name to determine which property value to use.
<%= Html.TextBox( "Name" ) %>
vs
<%= Html.TextBox( m => m.Name ) %>
Textbox does not give compile time error when you wrongly mentioned the property name. it will throw run time exception.
TextBoxFor is a genetic method so it will give compile time error when you wrongly mentioned the property name.
TextBoxFor will be helpful when we append two property names in view
#Html.TextBox( "Name" ,"value",new { #class="class"})
vs
#Html.TextBoxFor( m => m.Name, new { #id="txtValue"})

Resources