Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Pinal Bhatt 298 posts 390 karma points
    Nov 28, 2012 @ 03:53
    Pinal Bhatt
    0

    U4.11 Looks like Node.Url functionality is broken

    hi Community

    It looks like Node.Url functionaity is broken in U4.11

    I have following code:

       <ul>
    @foreach(var item in @CurrentPage.Parent.TechnewsPages)
    {
    <li><a href="@item.Url">@item.Name</a></li>
    }
    </ul>

    @item.Name works fine but for @item.Url, for all the items i am getting Url for the CurrentPage only.

     

    is this a know issue or a bug in  U4.11. Is their any workaround for this?

    Thanks & Regards,
    Pinal Bhatt

  • Stephen 767 posts 2273 karma points c-trib
    Nov 28, 2012 @ 09:32
    Stephen
    0

    Do you actually get the url for the CurrentPage, or do you get href=""? Can you look at the source? Trying to reproduce here, and @CurrentPage.Url or any @item.Url always come as empty ie href=""...

  • Stephen 767 posts 2273 karma points c-trib
    Nov 28, 2012 @ 09:52
    Stephen
    1

    Turns out, neither "Url" nor "NiceUrl" are properties of your document type, so item.Url is empty. If you want the nice url of that item, the correct syntax is:

    @item.NiceUrl()

    Stephan

  • Luke Alderton 191 posts 508 karma points
    Nov 28, 2012 @ 14:59
    Luke Alderton
    0

    You can do

    Umbraco.NiceUrl(item.Id)

    a good page to reference is: http://our.umbraco.org/documentation/Reference/Mvc/

  • Shannon Deminick 1524 posts 5269 karma points MVP 2x
    Dec 02, 2012 @ 22:42
    Shannon Deminick
    0

    In the razor macros (which are not the same as using MVC) there was support for using a .Url or .NiceUrl property on a node item however this is not the case in MVC. The reason is because If someone creates a property on their node called 'Url' or 'NiceUrl' they will never be able to access it because '.Url' or '.NiceUrl' will just return the actual URL for that content item which isn't ideal. The other problem is because the legacy INode has a .Url property attached to it where as the new IPublishedContent doesn't and this is because Url's are resolved through a NiceUrlProvider since resolving a URL should not be the responsibility of the model.

    The way to get the NiceUrl for a content item in MVC whether you are using @CurrentPage (dynamics) or @Model.Content (strongly typed) is to use the extension method NiceUrl() as Stephan has mentioned above.

    That said, when using @CurrentPage (dynamics) we need to go look for this extension method which has a teeny performance overhead so I will add a native NiceUrl() method to the DynamicPublishedContent class to call this extension method directly which will save on a bit of performance.

  • Shannon Deminick 1524 posts 5269 karma points MVP 2x
    Dec 02, 2012 @ 23:55
    Shannon Deminick
    0

    @Niels has mentioned on twitter that having a .Url property on @CurrentPage would be nicer than @CurrentPage.NiceUrl() ... which is possible, however as @Doug noted on Twitter, what if someone creates a 'Url' property on their document type? Well, we can handle that if we want and render the 'Url' property on the node that is defined on the document type and if a property is not found, then we render the NiceUrl. This is possible, but...

    To me this poses some issues. First this is kind of confusing, we are now offering multiple ways to acheive the same thing (if we use the same logic in razor macros):

    @CurrentPage.Url, @CurrentPage.NiceUrl, @CurrentPage.Url(), @CurrentPage.NiceUrl()

    Plus this is confusing if people have defined 'Url' or 'NiceUrl' as a property on their document type. The other reason why this is confusing is because it is not possible to have this same syntax for the strongly typed model. For example, we cannot do this:

    @Model.Content.Url 

    and have this return the NiceUrl of the item, that is because 'Url' does not exist as a property of IPublishedContent because it is not up to the model to return the Url and c# doesn't support 'extension properties' only 'extension methods'. This is why we have an extension method: NiceUrl() on IPublishedContent which will automatically do a Umbraco.NiceUrl(Model.Content.Id) for you. Also, just to mention that the NiceUrl() extension method does not need to be discovered, it will always be there by default because we are automatically importing all required namespaces in to the MVC views in Umbraco based on the web.config in the ~/Views folder, so you need not worry about discovery.

    In the end I propose not creating these .Url and/or .NiceUrl properties on the dynamic @CurrentPage because we already have @CurrentPage.NiceUrl() which is consistent with @Model.Content.NiceUrl(). This way we have one consistent/standard way to do things across both dynamic and strongly typed models and there is no extra work involved with this like importing namespaces into your views and you still get intellisense when using the strongly typed model.

    That said, if everyone really wants me to add .Url and/or .NiceUrl as properties on the dynamic @CurrentPage, then let me know and i can do it.

  • Niels Hartvig 1951 posts 2391 karma points c-trib
    Dec 03, 2012 @ 00:21
    Niels Hartvig
    0

    Warning: Angry founder rant, from a guy who thinks we got the priorities fucked up.

    First; a technical objection to something that would be an improvement (not saying it's the case here, just a general observation) is invalid and just plain stubborn. Second; the argument that 'what if you added a property called 'Url' is funny. You could say the same of Writername, Name, CreateDate and the about a dozen build in meta data we always have had. Never been a problem (even though there's never been validation).

    Extension methods are awful, because their discovery purely relies on your IDE and they make it super easy to made a really ugly patchwork of an API design (all while you can insist that your interfaces and models are clean and beautiful)

    What I did suggest was simply that since every published node in Umbraco have a URL, why not have a Url property? I couldn't care less about some interface that someone made, which makes it harder to do. Who are we trying to satisfy here?

    The important thing should be making Umbraco so it's super easy to use no matter what IDE you're using. And if we want consistency then mark that shitty extension method obsolete...

  • Shannon Deminick 1524 posts 5269 karma points MVP 2x
    Dec 03, 2012 @ 01:10
    Shannon Deminick
    0

    @Niels, first there's no reason here to be angry and priorities are not fucked up. As I've mentioned adding the .Url and/or .NiceUrl property is no problem with dynamics. Happy to add it if you want it'd be easy.

    As for extension methods, the argument for IDE is purely based on intellisense. When using dynamics like @CurrentPage there is no intellisense anyways. The only IDE out there that has intellisense that might not do extension methods is the old Web Matrix, the new one (v2) definitely does. As I mentioned, these extension methods in particular that are used for editors of Umbraco need not worry about discovery because the web.config in the ~/Views folder auto includes all these namespaces. I'm not lying here, this is the truth, they will never need to include a custom namespace in their views, it will always just work. This same concept goes for the TONS of other extension methods on IPublisehdContent including extensions like .Where(..), .Children(...), GetPropertyValue(...), IsVisible(), etc... 

    The end result is identical, to get the Url you can do:

    @CurrentPage.NiceUrl()  - using dynamics which have no intellisense anyways or

    @Model.Content.NiceUrl() - using strongly typed models - (which will give you intellisense in VS and Web Matrix)

    and this will work regardless of your IDE with no extra steps.

    Now as for .Url on strongly typed models... IPublishedContent does not have a Url property because when someone implements this interface it would then be up to them to generate the NiceUrl functionality, this is far from ideal. The other reason this isn't nice is because Media IS Content like we've been discussing for years. However, media doesn't have a NiceUrl... there's actually a thread about this on the issue tracker but this is down at the moment so i can't get the link. Having said this, because media doesn't have a URL perhaps Media is not actually 100% content, they need to be separated (again, there's details on the issue tracker about this)

    With all of this said, the only way to have Url as a real property of IPublishedContent is to change the interface which is a breaking change. If we do this, we might as well also seperate the media and content to different interfaces as discussed in the tracker thread.

    So, we can do this but the end result is really just the difference of this:

    @Model.Content.NiceUrl() vs @Model.Content.Url

  • Anthony Dang 1404 posts 2558 karma points MVP 3x c-trib
    Dec 03, 2012 @ 01:26
    Anthony Dang
    0

    My 2 cents...

    Personally I think it would be nice to keep .Url. I never really understood the need for NiceUrl() in razor as .Url always worked. 

    I definitely do not ever want to have to do: Umbraco.NiceUrl(item.Idwhen in current razor we can do .Url 

    In v5, media was content and was linked to as such. Media currently does not have a .Url or .NiceUrl(), but a .umbracoFile which makes no sense. Regardless of what you do with Media, it would be great to be able to access it via .Url like content.

     

  • Shannon Deminick 1524 posts 5269 karma points MVP 2x
    Dec 03, 2012 @ 01:29
    Shannon Deminick
    0

    @Anth, thx for the feedback. The .Url is totally cool for dynamic models (@CurrentPage)... like razor was. BUT the issue is being able to do .Url when you are using strongly typed models (@Model.Content) because Url is not a property. Again, if we think that this is a requirement we'll have to add some breaking changes to the next release and probably implement the changes listed on the tracker regarding media vs content and the IPublishedContent interface.

  • Shannon Deminick 1524 posts 5269 karma points MVP 2x
    Dec 03, 2012 @ 02:11
    Shannon Deminick
    0

    Once the tracker is back up and running I'll open a thread on the dev mail list about these changes for IPublishedContent since we'd want to get them in for 6.0 (major release)

  • Gareth Evans 140 posts 331 karma points c-trib
    Dec 03, 2012 @ 05:56
    Gareth Evans
    0

    Hi, 

    Thought I'd add my 2c. No, I'm not dead! Just been a bit busy so letting the MVC pros do their thing.

    In 4.8, I unified media and content and I believe it worked okay.
    The only obvious difference was that a media item didn't have a Url per sey, it had a path (usually, by convention, stored as umbracoFile)

    On DynamicNode (now superceeded) the .Url property would return umbracoFile if it was media or the NiceUrl if it was content.

    The end result was that users could just go .Url and not really care if they had a media item or a content item.

    I would suggest that we want to avoid as many hoops as possible for common operations, while umbraco.NiceUrl(id) is fine, or item.NiceUrl() is fine (both of these are perfectly acceptable) there's nothing better than simple - a content node or media node will pretty much always have a path or a url, so why not have .Url available, even if internally it maps to NiceUrl or the equiv. for media.

    Also, why NiceUrl; is this not a legacy term from before Umbraco had url rewriting for content nodes built in? Would there ever be a (non nice) Url for content?

    Gareth

     

  • Shannon Deminick 1524 posts 5269 karma points MVP 2x
    Dec 03, 2012 @ 06:04
    Shannon Deminick
    0

    hehe, yeah, NiceUrl() has been discussed on the mail list, i think in the future will just be Url() :)

    If we take the route of splitting Content and Media as I think we should (really wish the tracker was up and running with that link...) then I don't think we need to worry about .Url for media since people can just access the property that contains the Url (this has also been discussed on the tracker).

    So as I've mentioned, having .Url is easy for @CurrentPage (because it is dynamic, just like @Model in razor macros), the issue is having .Url on the strongly typed model of IPublishedContent since that will require a breaking change. This is easy to do but warrants a discussion on the mail list because if we are going to make this change we should also make the change to split content/media properly. 

    Also, we will probably create a new class like BasePublishedContent which implements IPublishedContent and it's Url property will automatically just call to the NiceUrlProvider to ge the Url. That way if people are implementing their own IPublishedContent, they would inherit from BasePublishedContent so that the Url property is handled for them.

  • Stephen 767 posts 2273 karma points c-trib
    Dec 03, 2012 @ 09:08
    Stephen
    0

    My 2 cents:

    From an end-user point of view, the situation with "traditional Razor" vs. "MVC with dynamic" vs. "MVC with strongly typed" is getting *rather* confused. Even the names are confused. I'd really like if we could at least tell people, OK, there is

    • "Macro Razor", ie what you use in macros when running in WebForms
    • "MVC Razor", ie what you use when running in MVC

    Then, everything in MVC Razor should be consistent, be it dynamic or strongly typed, so if it's CurrentPage.Url() then it has to be Model.Current.Url(). No exceptions, no excuses. The only difference should be CurrentPage.myProperty vs Model.Current.GetPropertyValue("myProperty") I guess.

    I support the use of a _method_ ie .Url() because what it does is actually _compute_ the url, which is not absolute and can depend on the context, whether we are previewing or not... (and if we go further with 1-to-1 multilingual it may even depend on the current culture). So it's not a property (the value of something) but a method (the result of a computation).

    As for medias, well, medias have no "url" so the .Url() method should return an empty string of some sort, anything else is going to be a "gotcha".

    Then we can have some sort of cheat sheet that maps Macro Razor to MVC Razor functionnality so people can see where the differences are.

    But really... at the moment I have to code some Macro Razor code for a customer, and, well, even I gets lost and start pestering about what's the right syntax to get this and that and what's the best option etc

  • Anthony Dang 1404 posts 2558 karma points MVP 3x c-trib
    Dec 03, 2012 @ 12:24
    Anthony Dang
    0

    I think it makes a lot of sense to have .Url since we already have .Created, .Updated, .Id, .Template etc.

    .NiceUrl() for the new class seems like it's come out of nowhere. Why not .Created(), .Updated(), .Id() ?

    I would even like to see .AlternativeLinks

    Basically I'd like to see every umbraco node property we see in in the content section actually be a property, not a method. And I'd like these to be in the strongly typed object. In other words, I like DynamiceNode.

     

  • Edwin van Koppen 156 posts 270 karma points
    Dec 05, 2012 @ 10:09
    Edwin van Koppen
    0

    I do have a sort of a solution.. use a dynamic object in the view

    @model ViewModel.MenuViewModel
    <ul>
        <li><a href="/">home</a></li>
        @foreach (dynamic page in Model.Children) {
            <li><a href="/@page.UrlName">@page.Name</a></li>
          }
    </ul>

    namespace W3S.Controllers
    {
        public class MenuController : SurfaceController
        {
            [ChildActionOnly]
            public ActionResult Part()
            {
                MenuViewModel MVM = new MenuViewModel();
                MVM.Children = Umbraco.Content(1804).Children.Where("Visible");
                return PartialView("Menu", MVM);
            }

        }
    }
    namespace ViewModel {
        public class MenuViewModel {
            public DynamicPublishedContentList Children { get; set; }
        }
    }

  • Funka! 398 posts 661 karma points
    Dec 05, 2012 @ 23:06
    Funka!
    0

    This is an interesting topic and discussion so thought I might jump in with some of my own commentary and thoughts!

    First, regarding any worry over someone creating their own custom property called "Url":  I have done this in the past, but my property names always start with a lowercase letter, so "url" has never conflicted with "Url". In fact, the back-office tries to default your property aliases to this intial-lower camelCase format when you create them, so I would imagine most people do this too. But as someone else already pointed out, this same problem exists with *any* of the other reserved names like Id and Name and Children, etc., so doesn't seem like anythihng to really worry a lot about.

    Next, maybe this is more of a question/ignorance on my end than anything, but regarding the comments about Media items "not having a Url" to me seems confusing. Yes, we call this "umbracoFile" currently, but that was actually something I found confusing when I first started with Umbraco. Of course now I understand how this works and that this is just a convention for the "upload" data type to be named, but regardless of how Umbraco likes to call things, in my opinion, a media item *should* have a Url.  If I have a PDF, it should have a Url I can link to. If I have an image, it should have a Url I can place into an image tag. Whether this is called a path or a Url seems to me, the layman, like it's all the same thing, but still an integral thing to have. (I think this is what Gareth is saying too.) I can probably predict now my own rebuttal to this which is what to do when there are multiple files on the same media item, like crops or whatever, so maybe that is why there is hesitation to have "Url" on media items?

    Finally, regarding Shannon's comment regarding a Url property on the strongly typed model of IPublishedContent, which is mentioned would be a "breaking change..." I wanted to see why this was, so I took a look at the latest branch to see what this was all about, since I've never actually used IPublishedContent and in fact thought it was only a 6.0.0 thing and thus wasn't sure what there was to "break", but see it is a 4.10 thing so never mind that concern.  Given my earlier paragraph about why a Media item can't have a Url, I perhaps would need to study the code to see why adding a new member to this interface would actually break anything? If there are other implementations of this interface where a Url would NOT make sense, then can't those just throw a NotImplementedException? (So yeah, I suppose that would maybe cause some 3rd party things to break, but this seems early enough that I might guess there's not much out there yet actually doing this?)

    To conclude, so much of IPublishedContent seems so similar to DynamicNode already except for this one property, in the end I guess whether it's a method or a property or an extension will likely not make any difference to me, just so long as once everything is said and done we could maybe get a nice "cheat sheet" similar to the one we had for Razor + DynamicNode? So far it's been very much like "Where's Waldo" to figure out how to really take advantage of 4.10+ features, it's been a bit of a roadblock to be honest and am just waiting for dust to settle before fully jumping on board.

    Thx!

  • Shannon Deminick 1524 posts 5269 karma points MVP 2x
    Dec 08, 2012 @ 21:41
    Shannon Deminick
    0

    Thx for more feedback, I will add the Url as a property of media too, however the base class implementation will throw an exception if the umbracoFile property does not exists. Other implementers will need to do what they want with this property of media.

    Just some quick info, DynamicNode is not the same as IPublishedContent, here's how the mapping works:

    • IPublishedContent will supercede INode
    • DynamicPublishedContent will supercede DynamicNode
    I'll just reiterate, adding any of these properties to DynamicPublishedContent including .Url is 100% ok without breaking changes, its the changes to IPublishedContent that breaks. In razor macros, people will DynamicNode which is dynamic, meaning no intellisense, etc... In MVC we support both, we have @CurrentPage = DynamicPublishedContent which is dynamic and supports nearly the exact same syntax as DynamicNode. Then we have @Model.Content = IPublishedContent which is strongly typed, I would bet that most people that can use strongly typed objects will and now this is possible with our MVC implementation, this includes strongly typed queries etc... 
    We've created this implementation so that there would be very limited 'barrier to entry' or 'roadblock' because it should feel nearly identical as razor macros, however we've added support for strongly typed objects which should make many people's development experience much much better.

     

Please Sign in or register to post replies

Write your reply to:

Draft