I know ViewBag is used in Razor view engine but not sure how to access viewBag's dynamic properties in aspx view engine.
As I want to put text inside Html.ValidationSummary() through Viewbag I am using the following syntax but getting error "has no applicable method named 'ValidationSummary' 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."
Syntex:
<%= Html.ValidationSummary(ViewBag.ValidationSummary)%>
It is complaining because ValidationSummary has no single parameter overload that takes a parameter of type dynamic; that is what ViewBag properties are. Cast the property to a string.
<%= Html.ValidationSummary((string)ViewBag.ValidationSummary)%>
Related
In the following code of the example application of VS2015:
#model LoginViewModel
<p>
#Html.DisplayNameFor(m => m.Name)
</p>
I want to know how the compiler knows that m refers to the LoginViewModel if I never said that m is an alias for LoginViewModel.
And I would like help understanding the lambda expression of DisplayNameFor. Why it requires a lambda if we could just pass the string m.Name? How is it used here?
The given Razor template will be compiled, so the Razor view compiler can do some magic here.
The compiler knows the type of your model because of the #model directive (without the #model directive the compiler falls back to dynamic).
If you look at the #Html.DisplayNameFor directive, then the Html instance is an object of the type HtmlHelper<TModel> where TModel is the type given by the #model directive. In your case is the concrete type HtmlHelper<LoginViewModel>.
Now the HtmlHelper<LoginViewModel>.DisplayNameFor method is stongly typed and the compiler can figure that 'm' (which is only a parameter name) is of type LoginViewModel and that the lamdba expression returns a value from the model.
During runtime the DisplayNameFor method is executed by providing your model object as parameter 'm' the expression returns the object of the model member (or the object the expression returns) and the MVC framework can inspect the object (Type, Validation Attributes, etc.) and produces the appropriate html based on internal or custom templates.
If you would just pass a string, then MVC would not be able to get the needed type and validation annotations (and much more information).
Your first question: It passes LogonViewModel to #Html.DislplayNameFor method since you have define it on you first line as your model (#model LoginViewModel)
Aslo as it mentioned here:
What is the #Html.DisplayFor syntax for?
Html.DisplayFor() will render the DisplayTemplate that matches the
property's type.
If it can't find any, I suppose it invokes .ToString().
DisplayNameFor is a strongly typed HTML helper. These were first introduced in ASP.NET MVC 2. The purpose of them (as per the linked article) is to...
...provide a nice way to get better type-safety within your view templates. This enables better compile-time checking of your views (allowing you to find errors at build-time instead of at runtime), and also supports richer intellisense when editing your view templates within Visual Studio.
If you want to understand the innards of how they work, the source code is available on GitHub.
I'm sending the following model to my view.
return View(new { url = returnUrl });
In the view, I'm don't want to specify any particular class for my object (since I wish to keep it flexible and elastic for now). So, the #Model is the apparently an object and as such, it's got no url property. Hence the error.
Additional information: 'object' does not contain a definition for 'url'
Now, I do know that the thing inside the object has url property. I have assigned it to it and I also see it when watching the variable as the exception's been thrown.
My question is how to access the field. Is my only option declaring a class and type the model using #model Something? I can't use as keyword to type it to var...
In "plain" C# we can do something like this.
var some = new {thing = "poof"};
string output = some.thing;
How do I do the equivalent of it in CSHTML file under Razor?
Strongly-typed view models are the way to go. Create a type that suits the needs of the view and treat reusability/duplication as a secondary concern.
However, let me explain why your attempt did not work.
It is legal to pass an anonymous type--even between assemblies[1]--as long as it is cast to object. In fact, the MVC framework assemblies consume anonymous types in many helper methods. Those anonymous types are then evaluated using reflection (optimized by caching).
1: I believe there are some caveats to this, and it certainly isn't good practice in most cases.
A view is compiled into a class so that it can be executed. Part of the class's contract is the type of model it expects, as indicated by #model in your view markup.
This presents a problem with anonymous types, as you cannot indicate their type in your view and type object doesn't expose the properties you set when declaring the type. Thus, you end up with a view that only knows that its model is an object.
Again, use strongly-typed models, or the ViewBag if you truly only need one or two values.
However, to prove that the anonymous type can be passed to the view, look at this (horrible) example:
Controller
return View( new { property1 = "hello world"} );
View
#model object
#{
var rvd = new RouteValueDictionary( Model );
}
#rvd["property1"]
We passed an anonymous type to the view as an object, and then read the object's properties using RouteValueDictionary.
You can use ViewData and ViewBag to send objects to the view page, in your case you can write in the controller something like this:
ViewData["url"] = url ; //Or whatever
return View();
Now in the view you can simply use your object example:<div>#ViewData["url"]</div>
But mainly in MVC it is more recommended to use strongly typed View Models
You may want to look into using the dynamic type in C#. See https://msdn.microsoft.com/en-us/library/dd264736.aspx for details.
While the standard would be to use a strongly-typed view model, there are some scenarios where you might want to use dynamic as your model type (or as a property of your strongly-typed view model), such as in a CMS where the properties are built dynamically by the CMS Provider.
Example view:
#model dynamic
<p>
Url: #Model.url
</p>
I'm trying to pass an object through an ActionLink to a method in an MVC controller.
The razor syntax:
#Html.ActionLink("Export to Excel","ReturnExcelOfViewableResponses",new { SearchObject = Model.SearchObject})
What's actually being displayed in markup:
Export to Excel
The controller method is being called just fine, hence no reason to post here. What needs to be done so that the actual values are passed into the actionLink instead of DTO.SearchObject? According to HTML.ActionLink method it looks like I have the right syntax (using MVC 4).
You should be able to pass the DTO, assuming it's just that, as the parameter into ActionLink:
#Html.ActionLink("Export to Excel","ReturnExcelOfViewableResponses",Model.SearchObject)
Any public fields will be added as a query parameter key/value pair.
I am trying to make a combination of a html helper and a Reder CSHTML.
In other words, how can I use a cshtml "template" with a html helper so I do not need to parse all the ugly HTML in the methods.
I am currently using #Html.Action but that is not preferable as it needs a working URL.
#Html.RenderAction("GetThreads", "Forum")
public ActionResult GetThreads()
{
return new EmptyResult();
}
This gives the exception:
Argument 1: cannot convert from 'void' to 'System.Web.WebPages.HelperResult
Do I always need to add a route in the Global.asax file? Or are there ways to call Actions without it (like HTML helpers, but with a template file).
I have been trying with RenderPartial, but I keep getting these errors: Argument 1: cannot convert from 'void' to 'System.Web.WebPages.HelperResult'
Surround it with #{}
#{Html.RenderPartial("_SomePartial");}
Use #Url.Action to get the URL of an action. I think that is what you need.
Or #Html.RenderPartial or #Html.RenderAction will spit out the view to the page.
EmptyResult won't render a view. That might be your problem.
You might be looking for RenderPartial.
I've been trying to convert my aspx pages to cshtml and having an issue with rendering partial pages from another folder.
What I used to do:
<% Html.RenderPartial("~/Views/Inquiry/InquiryList.ascx", Model.InquiryList.OrderBy("InquiryId", MvcContrib.Sorting.SortDirection.Descending));%>
I would think that the equivalent would be:
#Html.RenderPartial("~/Views/Inquiry/_InquiryList.cshtml", Model.InquiryList.OrderBy("InquiryId", MvcContrib.Sorting.SortDirection.Descending))
This is obviously not working, I am getting the following error.
CS1973:
'System.Web.Mvc.HtmlHelper'
has no applicable method named
'Partial' 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.
How would I achieve this with using the Razor view engine?
The RenderPartial does not return a string or IHtmlString value. But does the rendering by calling Write in the Response.
You could use the Partial extension, this returns an MvcHtmlString
#Html.Partial( ....
or
#{ Html.RenderPartial(....); }
If you really want RenderPartial
The compiler cannot choose the correct method because your Model is dynamic. Change the call to:
#Html.RenderPartial("~/Views/Inquiry/_InquiryList.cshtml", (List<string>)Model.InquiryList)
Or to whatever data type InquiryList is.
Remember to include your strongly typed #model directive in your new Razor view. It is an easy step to miss when converting views from .aspx to .cshtml. If you forget, that 'System.Web.Mvc.HtmlHelper' has no applicable method named 'Partial' error message could appear.