I was wondering if someone here could shed some light on some questions I was having lately about Razor.
1) Basically, I wanted to split section definition into multiple parts? Why? Because I wanted to.
Sadly using #section "sectionname" twice threw an exception.
Looking deeper into the Razor source, I saw that Razor checked if a section had already been defined and threw an exception if it was already defined.
As Razor uses delegates to render sections, I changed the code to use Delegate.Combine (if a section had been defined before), and it worked, I was now able to create a Section that was declared twice (or more).
2) When a section is defined in a View but not rendered in the layout page an Exception is thrown. I haven't seen an elegant solution to overcome this. If I want to use a View page with multiple layout pages... This is kind of a problem.
Looking at the source (again) there's just a foreach that checks if every section defined in the view has been rendered, and then it throws an exception if a section hasn't been rendered.
I have thought of some solutions (especially for my second question, inheriting from the view base class and exposing the non-rendered sections to the layout page and doing some handling), but they seem... kind of like hacks. Are there any better solutions then actually changing the source?
Not really important, but if anyone also has any insight on the design decisions that led Razor to be this way, I'd also be grateful, as this seems to be a very restrictive design.
update:
#davidferguson and #takepara you've got it wrong. My problem isn't with defining a section in the layout, and not defining it in the view, but the other way around. Defining it in the View but not defining it in the layout.
1) Unfortunately that was a design decision made early on in the product as there is huge issues around merging sections together and in what order. Not saying that we couldn't do it but with the time frame we had it just wasn't possible to support it as a first class citizen in all scenarios.
2) This is an interesting idea. There really isn't an good solution to this other than changing the source code. However, I have opened an issue for a feature for vNext that would allow for this type of scenario. (No promises that it will make the cut though)
To stop an exception being thrown when a section is not used on a view use the required parameter.
#RenderSection("sectionname", required: false)
using this if any view does not implement this section no exception will be thrown.
Defining Default Content For A Razor Layout Section
This is very nice entry.
Related
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.
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.
I ran into a problem with inheritance in a current iOS project:
The current inheritance structure looks like this (Simple representation):
CommonWidget
AWidget
AWidgetDetailsView
BWidget
BWidgetDetailsView
RoundWidget
RoundWidgetDetailsView
CommonWidget declares and implements several layout methods for shadows, background, icons, buttons, etc. In the A... & B... classes, this code is reused, since the views look similar, but have different models. So far no problem \o/
The Designer now introduced a new kind Widget, the RoundWidget, that looks somewhat different, yet the RoundWidgetDetailsView looks like the other _DetailsViews.
This leads to the problem: RoundWidget overwrites the layout methods of CommonWidget which means that RoundWidgetDetailsView obviously uses those methods as well.
More or less, it comes down to an alternative to the accepted answer of this question:
How to call a method of super.super?
Or, simply put, any suggestions on how to change the inheritance structure to avoid running into the same problem in the future?
Thank you in advance for your time!
Tobias
Is there any example of binding any sort of collection to a TableLayout in android? I keep receiving the message/warning that binding failed for attribute ItemSource LocationQuantities. All of the other bindings to the view model work as normal, but the list doesn't bind to the TableLayout. At first I thought my problem was binding to a dictionary but I was able to bind to a dictionary with other Mvx layouts (listview etcs.)
I can't seem to find in any of the N+ code examples or anywhere else on the web where a TableLayout is actually used in an mvvmcross app. I'm sure I'm just doing something stupid simple wrong here.
<Mvx.MvxTableLayout
p1:id="#+id/PartLocationQtyTable"
p1:layout_width="fill_parent"
p1:layout_height="wrap_content"
p1:layout_below="#id/PartDetailPriceLayout"
p1:padding="5.0dp"
local:MvxBind="ItemSource LocationQuantities"
/>
I've tried the above as well as with a custom template. The above example just uses a list of strings.
Any help would be appreciated
The only obvious problem I can see with your code is that it uses ItemSource whereas all the list-based layouts use ItemsSource - see MvxTableLayout.cs#L89
Beyond that, I guess you'll also want to make sure that your templates for TableLayout are TableRows - so that they can be loaded as rows. Obviously we can't see your item templates currently as you've not included them in the question.
I've got to admit TableLayout isn't something I've ever personally used in a production project - just not something I've yet needed to use.
What areas get affected by it?
code readability? maintainability? performance? security? any other?
my views have been using something like
if(Model.Showthis) {<div id = "showthis">...</div>} }
and does doing something like the following have security implications? --
<%if (HttpContext.Current.User.Identity.IsAuthenticated && item.Poster.UserName == HttpContext.Current.User.Identity.Name)%>
<%{%>
...
<%}%>
yes I read "if" considered harmful in ASP.NET MVC View (.aspx) files? too, but it didn't exactly specify what areas get affected by it. I mean I wanted to make sure there are no security and performance implications, which the link didn't answer exactly
I think the stigma persists from the transition from ASP to ASP.NET Forms. MVC is a different beast. With MVC3 and Razor it should help break the stigma and allow for more readable, easier to write Views.
That said, Domain and Business logic should never be in your template. But I see no problem, and frequently make use of conditional statements and loops to render UI in my Views.
I don't see an issue with it as long as the branching logic is purely for UI concerns. With that in mind I would change your second if to:
<%if (item.Poster.UserName == Model.CurrentUserName)%>
<%{%>
...
<%}%>
And set your model up so that the CurrentUserName property looks like this:
public string CurrentUserName
{
get
{
return HttpContext.Current.User.Identity.IsAuthenticated
? HttpContext.Current.User.Identity.Name
: String.Empty;
}
}
Or even better if you're going to be checking author against current user a lot in your system, offload that property to a helper class that can be reused from multiple models. Basically I wanted to get the implementation detail of what the current user's name is out of the view.
There's nothing wrong with if else statements in your view template. What you want to avoid is business or model logic in side your view template. If the conditional is directly related to user interface, then it belongs in the view.
Yes, it can be a bit difficult to read because of the mix of HTML and C#, but so long as your view logic is in your view, and your model logic is in your model, you are properly maintaining separation of concerns.
With your second sample; it might make more sense to only have your Poster available to the View if the correct user is logged in in the first place; this seems like more of a Controller thing than a View thing to me.
A lot of people see if statements in the View and cringe, because it reminds them of classic ASP. But the problem with classic ASP was never that there was code and HTML in the same place; it was that there was business logic and presentation logic in the same place.
Edit Also, perhaps duplicate of "if" considered harmful in ASP.NET MVC View (.aspx) files?.
Why are they bad?
As many people have already suggested it's because it can be a warning sign that business logic is leaking into your views which is a bad thing. Or that you are trying to do too much in your view. Often it's easier to setup the necessary data in your controller and just pass everything required (including any computed values) and have your view render it straight out. The flatter and simpler your view model is the better.
I don't think there is anything wrong with using if/else's for the true purpose of conditionally rendering UI. For example, if a user is logged in render this partial if they aren't than render something else.
I think a lot people get taken back and draw a hard and fast 'it's bad practice' because it can easily lead to tag soup. This phenomena has already been highlighted as a carry over from the asp.net webforms engine. Whilst still a good thing to be aware of, it is likely less of an issue with the razor engine as it's much cleaner and requires less syntax to achieve the same thing. The automatic switching in and out of C#/VB code to html and back is very simple with only an # required to re-enter a code block. I don't think this will create tag soup in the same way that angled brackets did <% %>. The amount of noise in the latter was what most people objected to (and rightly so).
Lastly, circumstances depending, if you find you are starting to get a lot of if/else logic in your view sometimes it is cleaner to put that into a HTML helper. I can't find the reference but I remember Rob Connery once saying that if you find yourself starting to write if statements in your view than it's a candidate for a html helper.
Is there performance of security concerns?
I don't think there is going to be any noticable performance differences or security concerns with what you are asking. But considering an authentication check like that is likely to be used in multiple views I would put it into a Html helper.
If-else blocks are not bad specifically. Code in views is bad because you are mixing HTML markup with code. ASP.NET MVC is bad for separating static page design from dynamic UI code. Web Forms is better at separating static and programmatic UI elements.