T4MVC: Strongly typed partial? - asp.net-mvc

I'm using T4MVC in my MVC 5 website. In a view, I have something like:
#Html.Partial(MVC.Shared.Views.ViewNames.Foo, Model.FooBar)
The Foo view expects a certain type, which is defined with #model, but Model.FooBar might have a different type. This error is not detected until runtime.
Is there a way to use T4MVC to render the partial with a typed method, like we can use ActionLinks, maybe something like:
#Html.Partial(MVC.Shared.Views.Foo(Model.FooBar)) // Error: Foo() expects Argument of type ...

Short answer is that T4MVC currently doesn't support fully strong typing this scenario.
It's something that could conceivably be done, but it would present challenges. Specifically, T4MVC would need to parse the view to determine the model type. Currently, it never parses views, but only detects their existence.

Related

What is the difference between Dynamic and Strongly Typed Views in ASP.Net MVC

I got a url http://www.asp.net/mvc/overview/views/dynamic-v-strongly-typed-views
they create a not strongly typed view but at they refer #model dynamic at top of the view.
but rest of the code looks like normal strongly typed view. anyone can tell me what is the difference between Dynamic and Strongly Typed Views in MVC.
When one should use dynamic view. discuss with example when dynamic view is required ?
The difference is that a dynamic view won't enforce compile-time type-checking (binding to properties etc). You can name and bind any property you want. At run time, if it can't find it in the model, that's when you'll get an error. It's the same as the dynamic keyword in the language.
As to why or when to use it, generally speaking, don't. It's a workaround. Write a wrapper class, write the DTO, write an adapter, there's plenty of ways to make a strongly typed object to bind to. Implement an interface or something.
Rarely you might come across a situation where it's just not feasible (legacy code, 3rd party libraries?) to do it the "right" way. That's when you might be stuck with it. Run time errors are not fun to try to recover from - try to never use dynamic views.
The only time I personally have used it was to mock up test layouts and I didn't want to actually create full models yet. I'd not use it for production code.

Can I make a razor file optionally be a template file (RenderBody or RenderSection)

When I have RenderBody or RenderSection, and I try to use a template directly, it gives an error:
The file "~/Views/Home/Form.cshtml" cannot be requested directly because it calls the "RenderSection" method.
I have a form that has some basic fields, but in one instance, I want to extend the form with more fields (the Model inherits from the original).
Maybe I should just create the basic fields in a shared file, but this would work if it wouldn't throw the error above...
In Razor, everything is a view. "Partial views" are just views that don't utilize a layout, while the more traditional "views" are views that do. A "layout" is merely a view that at least calls one method, RenderBody. RenderSection, is likewise layout-specific. By making a view a layout (by calling methods like RenderBody, RenderSection, etc., it can no longer be used as "view" or "partial". This has to do with the way Razor handles view processing. By the time something like a partial is being rendered, there's nothing that can be done with something like RenderBody, so Razor raises an exception.
Long and short, you can't use a layout as a partial, which seems to be what you're trying to do here. Without more information about what it is that you're actually trying to achieve, it's not really possible to help you further than that.

Pass anonymous type as model in MVC 3 Partial View

I am refactoring an MVC 3 application, and moved a set of similar items into a partial view so I can keep that template DRY. Since the pieces don't all have the exact same properties, I am creating anonymous types like this:
var model1 = new { Description = "description 1", Message = "message 1" }
and passing them to the partial view like so:
#Html.Partial("_Partial", model1)
The partial view is then attempting to render certain blocks based on existence of a specific property, i.e.
#if (Model.Description != null)
{
#Model.Description
}
My issue is that even though I can see and navigate the Model object in the watch window during execution, I get a RuntimeBinderException in the if test that states 'object' does not contain a definition for 'ShowApplied'. I can obtain the values through reflection by calling (Model.GetType().GetProperty("ShowApplied").GetValue(Model)), but would much rather use the format shown in my code sample. I have been unable to find a clean solution...
How can I pass an anonymously-typed object to a partial view and access its properties directly? I feel like there is something simple I'm missing...
Why am I able to see the Model properties while debugging, but not access them from code?
EDIT
I am specifying #model dynamic.
Using an interface requires creating non-anonymous types because, as this answer explains,
An anonymous type cannot be cast to any interface or type except for object.
Insights from the comments (thank you) imply I have 2 options, since (as the answer to the linked question points out),
Anonymous types are internal, so their properties can't be seen outside their defining assembly.
and therefore are inaccessible to the Razor binding engine.
Use #Html.DisplayFor("amount") and deal with not having IntelliSense, reference lookups, etc.
Create classes that implement a common interface and bind my partial view to that interface.

RenderAction cannot be used with type arguments (MVC 5)

I'm new to ASP.NET MVC. A project that I am attempting to upgrade from MVC 3 -> MVC 5 has most of its calls to RenderAction, ActionLink etc in a format that is different to what I've seen in tutorials for MVC.
Specifically an invocation of a method looks like this:
#{Html.RenderAction<MyControllerHere>(c => c.MyAwesomeMethod());}
Razor is reporting the error:
The non generic method ...RenderAction(System.Web.Mvc.HtmlHelperString) cannot be used with type arguments.
Is this syntax still supported in MVC?
If so, what is the type argument referred to in the error?
If not how does this translate to current syntax?
I'll address your questions individually:
Is the syntax still supported?
Not as far as I know. I couldn't find an official source to confirm this, but as far as I understand, it was temporarily available as part of MVC Futures.
What is the type argument referred to in the error?
The C# type argument passed to the call to RenderAction. In your example, it is MyControllerHere.
How does this translate to current syntax?
Assuming your controller follows the default convention of having the Controller name suffix, such as MyController:
#{Html.RenderAction("MyAwesomeMethod", "My");}
I haven't tested this, but I believe it's mostly right.

ASP.NET MVC strongly typed views or not?

What is the best practice - to use only strongly typed views without any parameters, that passes through the ViewData dictionary, or it's a not bad idea to use something like this in a view:
<%: (string)ViewData["helloMessage"]%>
Thanks.
You should prefer strongly typed views. In some cases you need only one string like in your example, which doesn't belong to a model, then it is OK to use it. The other way is to encapsulate this variable into a class and pass the class to the view. The result would be a strongly typed view :-)
I personally don't like magical strings.
There is nothing wrong with using "magic strings"
But they are subject to typing errors.
In MVC 3 there is a dynamic object ViewModel in controller wich corresponds to a View object in view.
So you can assign ViewModel.MyData="something"; in controller and use it in your view as #View.MyData
It is kinda a better way to go.
Having only strongly typed views benefits from compile time checking.
And it is up to you to decide.
Personally I use dynamic object.

Resources