Copied to clipboard

Flag this post as spam?

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


  • Kieron McIntyre 116 posts 359 karma points
    Oct 09, 2013 @ 10:18
    Kieron McIntyre
    0

    Working with a mature WebForms

    I have a mature webforms Umbraco v4.11 implementation but it tends not to use any webforms functionality, i.e. postbacks/viewstate etc. and instead rely purely on a more barebones approach or ajax where form submittal is required.

    Personally I hate the project and wish that it was MVC but it would not be financially viable to move the project to an MVC implementation, so I'm looking for an alternative to implementing elements like forms that allow for a more MVC-like approach.

    I have used the MVCBridge project but this does not support MVC4. Does anyone have any ideas on implementing a more MVC approach into a mature webforms project? Or does anyone have any patterns or techniques they use for working with webforms projects?

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 11:07
    Martin Griffiths
    1

    Hi Kieron

    I'm smack bang in the middle of a conversion of my site from webforms to MVC. Initially i'm doing this on 4.11.9 but will move up to 6.x once we've dumped Courier. One of the key things I completely mis-understood at first is once you switch your site into MVC mode, rather miraculously masterpages (webforms) continue to co-exist quite nicely alongside anything new in MVC! Quite how the two techs work along side each other is a mystery to me, I assume there's combination of Umbraco/Microsoft practices at play here....but why the Umbraco team arent jumping up and down and advertising the fact....I dont know!

    This was a revelation and meant I could take a much more staged approach to my conversion and not feel like I had to rush in and change everything in one go.

    So for me stage 1 has been to switch over all of my masterpage templates to views and partials. Macros that use XSLT have remained for now, and may or may not get converted to macroscripts in the future. The caveat is macro based user-controls or any custom dlls that rely on the webforms page lifecyle/event model. These HAVE to be converted to views or macroscripts, I've used surface controllers with custom models for this successfully, although my biggest issue was passing in my custom model while continuing to inherit from the Umbraco model. The documentation says its possible in a partial, but in the end I had to pass my model over to a custom view via @Html.Action  I just kept getting an error saying i was passing in object mymodel.model when it was expecting umbraco.model! Very annoying!

    I hope this is of use to you

    Martin

     

     

  • Kieron McIntyre 116 posts 359 karma points
    Oct 09, 2013 @ 11:15
    Kieron McIntyre
    0

    Thanks for the answer - yes, I was aware that the masterpages could co exist with views - you just can't reference views from masterpages etc.

    I would very much like to move to using views instead of masterpages, but it's the risk of introducing errors and unnecessary work when the client hasn't paid/asked for it.

    I'm just wondering if there's a middle ground - a better implementation pattern for webforms.

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 11:30
    Martin Griffiths
    0

    I suppose it depends on your site implementation, ours is very code light in the masterpages and very code heavy in XSLT. In fact just about all of the heavy lifting on our site is done in XSLT. So moving over to MVC is very easy for us.

    I'm not aware of any middle ground of the two main techs, and are like comparing apples and pears anyway the approaches are completly different.

    In contrast I'm not so sure what we'll do about our XSLT code in the long term, we'll probably leave it well alone unless it's either dropped from Umbraco or if any of it requires a re-write! Personally I bug bear our XSLT over anything we've done in webforms! I've never been much of a fan of XSLT. 

    I think the point i'm trying to make here is you can take a far more pragmatic approach to your code. Change only what you need to change!

    As far as I know the Umbraco team have no plan to remove support for the older techs... so if it works...

    Martin.

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 11:57
    Sebastiaan Janssen
    1

    @Kieron it is actually SURPRISINGLY simple to change your master pages over to views, if you are not using forms it is super easy and you should not run into errors, have a read here: http://umbraco.com/follow-us/blog-archive/2013/7/14/moving-from-webforms-to-mvc.aspx (especially the "Convert Masterpages to MVC Views" section).

    Basically what you do is find anything that has "runat=server" on it and replace it, the cheatsheet shows it's only a handful of things that need updating.

    My advise: spend half a day, take 2 hours of client time and 2 hours of your free time and see if it's viable.

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 12:13
    Martin Griffiths
    0

    Hi Seb

    I actually tried that tutorial to convert one of our user controls which was pulling in a bunch of YouTube videos from our feed. I couldn't get it to work with a partial (Umb 4.11.9).

    Every time I tried to pass in my model it just started running the view code without the surface controller, resulting in object instance errors. In frustrastion I tweaked the inheritence of the views slightly but then got errors along the line of you tried to pass in model mymodel but it was expecting umbraco.templatepage.

    In the end to get it to work I used @html.Action but I could only pass my model into that. Trying to inherit from templatepage resulted in the error described above.

    Martin.

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 12:25
    Sebastiaan Janssen
    0

    @martin Sure, I was referring to the specific want of Kieron who says he doesn't depend on webforms too much.

    Not sure what your user control code looks like but it should be fairly easy to rewrite properly in MVC. It's most likely that there's something simple missing in what you were trying to do. :)
    If I had time to dive into that I would try to help, but unfortunately I haven't at the moment! :)

  • Kieron McIntyre 116 posts 359 karma points
    Oct 09, 2013 @ 12:36
    Kieron McIntyre
    0

    Thanks for the reply Sebastiaan. I did see that article and was toying with the idea. The thing that concerns me is that I have 40+ masterpages, nested and 3 of which are pretty hefty webforms that do use postbacks and a bespoke MVP implementation that we inherited. So I would have to maintain two base layouts and the given that this is not a small site, the testing time would be large.

    I'll look into it further though, it may just be worth it.

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 12:42
    Martin Griffiths
    0

    @Seb in my experience I was left scratching my head a lot, which makes what looks like a "simple" 2 hour webforms conversion a whole day task!

    MVC is a radical shift in methodology and its this shift which takes up precious time learing, not really something you can pass on to your clients unfortunately!

    For me I think my problem was every code example seems to involve form building using BeginUmbracoForm, which is fine if you want to capture user input on a POST action. I didnt need any of that! I just wanted the surface controller to go out and grab a bunch of videos using the .net YouTube API and return them to a view in a standard list with paging. I thought it would make sense to pass the paging out as actions too, but that caused me all sorts of routing issues! So in the end I did it the macroScript way and shoved all of the paging logic into the view itself!

    M

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 13:36
    Sebastiaan Janssen
    0

    @martin Cool, that's pretty easy to do by creating a [ChildOnly] action. Example:

    In your template (or MacroPartial) you do:

    @Html.Action("RenderVideos", "Videos")
    

    So: use the RenderVideos action on the VideosController

    The controller can do:

    public class VideosController : SurfaceController
    {
    [ChildActionOnly]
        public ActionResult RenderVideos()
        {
            var model = new VideosModel();
    
            foreach (var video in videos)
                model.Videos.Add(video);
    
            return PartialView("Videos", model);
        }
    }
    

    And finally you'll need a View for the list of videos you want to show, something like: Views\Videos\Videos.cshtml:

    @model Your.Models.Namespace.VideosModel
    
    @foreach (var video in Model.Videos)
    {
        //video html
    }
    

    That's all there is to it.

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 13:38
    Sebastiaan Janssen
    1

    @kieron Yeah the webforms are going to be a problem and I would not want to maintain two "master" layouts! :(

    "just" convert the webforms to MVC man, you know you want to! ;-)
    disclaimer: just messing with you.. :)

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 14:51
    Martin Griffiths
    0

    @Seb

    Yep that's pretty much what I did, but try adding another action inside the template for say paging, it fires off a custom route if ChildActionOnly is removed or is refused if it's present.

    Also that way you cannot pass in/inherit from IPublishedContent.

    M.

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 15:22
    Sebastiaan Janssen
    0

    @martin ???
    [ChildActionOnly] just means: this is not routable and can ONLY be called from Html.Action.
    I just added another [ChildActionOnly] action and it works just fine..

    @Html.Action("RenderSomething", "Search")
    

    Controller (just added new action to VideosController):

        [ChildActionOnly]
        public ActionResult RenderSomething()
        {
            var model = new VideosModel();
            model.PageName = "hello";
    
            return PartialView("Something", model);
        }
    

    New Views\Videos\Something.cshtml view:

    @model Your.Models.Namespace.VideosModel
    
    <h1>@Model.Name<h1>
    

    Your template inherits from UmbracoTemplatePage and a MacroPartial from PartialViewMacroPage so you have all the IPublishedContent you need there. Where else will you be accessing the content? In your controller?

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 15:30
    Sebastiaan Janssen
    0

    Oh and if the answer to the last question is yes:

    var currentPageId = UmbracoContext.Current.PageId.Value;
    var publishedContent = UmbracoContext.Current.ContentCache.GetById(currentPageId);
    

    This should get you there.. :)

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 16:15
    Martin Griffiths
    0

    @Seb

    Thanks a lot for the code examples I see where you're coming from and it might be that i'm not using a "macro partial" as such, but then again I may be?? LOL.

    Ok so lets give you a better idea...

    Template view (Multimedia.cshtml).

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
      Layout = "Page1.cshtml";
    }
    @section content{
        @Umbraco.RenderMacro("NavigationTabs")
        @Umbraco.Field("introText", insertBefore : "<p class=\"intro\">", insertAfter : "</p><div class=\"hr\">&nbsp;</div>")
        @Umbraco.RenderMacro("RichBodyText")
    
        @Html.Action("YouTube""YouTube")
      }
    

    What I really wanted here was a partial...But anyway the action calls another view in a folder in views called "YouTube.cshtml". Does that make it a macro partial? Or do I have to physically create a macro in the back office like with MacroScripts??

    Then the controller...

      public class YouTubeController : SurfaceController
        {
        const string YOUTUBE_CHANNEL = "";
        const string YOUTUBE_DEVELOPER_KEY = "";
    
        public ActionResult YouTube()
        {
          //we will create a custom model
          YouTubeModel vm = new YouTubeModel();
          YouTubeRequestSettings settings = new YouTubeRequestSettings("Staging Youtube", YOUTUBE_DEVELOPER_KEY);
          YouTubeRequest request = new YouTubeRequest(settings);
          string feedUrl = String.Format("http://gdata.youtube.com/feeds/api/users/{0}/uploads?orderby=published", YOUTUBE_CHANNEL);
          Feed<Video> videoFeed = request.Get<Video>(new Uri(feedUrl));
          vm.Video = videoFeed.Entries.ToList();
    
          return PartialView("YouTube", vm);
        }

    In the controller I wanted to add all of the logic for paging without having to resort to adding it all to the view/macro partial/partial god whatever it is this is it!

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<YouTubeModel>
    @using lcp.Controllers
    @using lcp.Models
    @using System
    
    @{ 
        int pageSize = 10; // How many items per page
        int page = 1;
        int count = 1;
        /* Set up parameters */
    
        if (Request.QueryString["page"] == null)
        {
          if (Request.QueryString["move"] == null) { page = 1; }
        }
        else 
        {
          page = int.Parse(Request.QueryString["page"]);
        }
        
        /* This is your basic query to select the nodes you want */
    
        var videos = Model.Video;
    
        int totalVideos = videos.Count();
        int totalPages = (int)Math.Ceiling((double)totalVideos / (double)pageSize);
        
        /* Bounds checking */ 
        switch (Request.QueryString["move"])
        {
          case "next":
            page++;
            if (page > totalPages)
            {
              page = totalPages;
            }
            break;
          case "previous":
            page--;
            if (page < 1)
            {
              page = 1;
            }
            break;
          default:
            if (page > totalPages)
            {
              page = totalPages;
            }
            else if (page < 1)
            {
              page = 1;
            }
            break;
        }
    }
    <ul id="paging_info">
      <li class="pipe first"><strong>@totalVideos videos.</strong></li>
    </ul>
    
    @foreach (var item in Model.Video.Skip((page - 1) * pageSize).Take(pageSize))
    {
    var duration = TimeSpan.FromSeconds(Convert.ToDouble(item.Media.Duration.Seconds)).ToString();
      <div class="team_member_container">
        <div class="one_third_column">
          <p>
            <img class="youtube" id="@item.Media.VideoId.Value" src="@item.Media.Thumbnails[1].Url" alt="@item.Title" style="width100%cursorpointermargin0 10px 0 0" />
          </p>
        </div>
        <div class="two_thirds_column">
          <p><strong><a class="youtube" id="@item.Media.VideoId.Value" href="#">@item.Title</a></strong></p>
          <p><strong>Duration:</strong> @duration</p>
          <p><strong>Published:</strong> @item.AtomEntry.Published.Date.ToShortDateString()</p>
          <p>@item.Description</p>
        </div>
      </div>
      
      count++;
    }
    
    <div class="pager_bar">
      <div class="prev grid_2">
        <a href="?page=@page&move=previous">Previous</a>
      </div>
      <div class="pages grid_8">
        <ul class="paging">
          @for (int p = 1; p < totalPages + 1; p++)
          {
            string selected = (p == page) ? "current no_link" : String.Empty;
            <li class="@selected"><a href="?page=@p" title="Go to page @p of results">@p</a></li> 
          }
        </ul>
      </div>
      <div class="next grid_2">
        <a href="?page=@page&move=next">Next</a>
      </div>
    </div>
    

    So where paging bit is, I wanted @Html.ActionLink("Prev"), next and numbered pages rather than doing all of the logic in the view as you see here and also save a whole bunch of request.querystrings too!

    Excuse my code, I threw it together so it's not very well optimised! lol.

    I assume due to the fact I'm calling an Action within an action by decorating the controller with ChildActionOnly, it's going to tell me where to stick it! It's an inheritance thing I guess? If take it off, the route becomes custom and it fires the action within an action but not all of the surrounding templates....just the dinky bit in the middle heh! Which is not very helpful!

    M.

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 16:22
    Martin Griffiths
    0

    @Seb

    Sometimes it's great going back to the drawing board and learning something completely new! Luckily for me I work for a company that affords me such luxuries, without having to dedicate precious home time! LOL.

    I'm sure you'll be telling me i'm doing it all wrong! It's as much about best practices as anything...much like inline code vs code behind was in the early days of webforms! ahhh the memories of moving from Classic ASP to ASP.net!

    Martin.

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 16:34
    Martin Griffiths
    0

    It's occurred to me to completely seperate the video list from the paging and maybe drop the paging into the multimedia view below the first action? That way I could call the two actions from within the same template level and hopefully pass in and out the necessary page data?

    It's an off the cuff idea..lol

    M.

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 16:34
    Sebastiaan Janssen
    0

    What I really wanted here was a partial...But anyway the action calls another view in a folder in views called "YouTube.cshtml". Does that make it a macro partial? Or do I have to physically create a macro in the back office like with MacroScripts??

    No a macro partial is just a partial view wrapped in an umbraco macro inheriting from UmbracoMacroPartial. You don't need one, you have the Html.Action in your template already. If you wanted to be able to insert the YouTube partial in the RTE or if you wanted to cache the YouTube partial you could create a macro partial. But as I said, it's not necessary, you're doing things from your template already, that's great.

    return PartialView("YouTube", vm);

    This will go look for ~\Views\YouTube\YouTube.cshtml and that will expect YouTubeModel as model (you're confusing route hijacking with doing stuff much more simply.

    So go to your YouTube.cshtml and wipe everything out of it (make a backup :P) Then try this:

    @model YouTubeModel
    @foreach (var video in Model.Video) {
       @video.Title<br />
    }
    

    That works, right? Keep your paging server side. So on first request do: vm.Video = videoFeed.Entries.ToList().Take(10);

    Use ModelBinding to your advantage, if you add ?page=1 to your querystring, you can catch that:

    public ActionResult YouTube(int page = 0)
    

    So when there's no querystring, the page is 0, otherwise the page is an int as provided in the querystring.

    Then you can start doing the paging calculations by using videoFeed.Entries.ToList().Count().. etc. So then you'll be doing something like (it's probably incorrect but do play with it):

    vm.Video = videoFeed.Entries.ToList().Take(numberOfItemsToTake).Skip(numberOfPages * numberOfItemsToTake);
    
  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 16:39
    Martin Griffiths
    0

    return PartialView("YouTube", vm);

    This will go look for ~\Views\YouTube\YouTube.cshtml and that will expect YouTubeModel as model (you're confusing route hijacking with doing stuff much more simply.

    So do I need to change this bit at all? Yes, I read about route hijacking and I was aware I may be getting it confused, Do I just return CurrentUmbracoPage? 

     

     

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 16:48
    Sebastiaan Janssen
    0

    No no, return PartialView("YouTube", vm); is perfect. Then you can build up that view like I said starting with:

    @model YouTubeModel
    @foreach (var video in Model.Video) {
       @video.Title<br />
    }
    

    Just to prove that you get a result. And then you can build it up from there. I mentioned route hijacking because that's usually what you'd use Umbraco.Web.Mvc.UmbracoViewPage

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 16:53
    Martin Griffiths
    0

    Yup thats all good works fine, but where and how do I build up a paging bar? Do I do that in the view? Outside the view? How are the page numbers pre-populated in the pager bar and how do I call @html.ActionLink to post/get the next/previous or absolute page?

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 16:55
    Sebastiaan Janssen
    0

    You put all of the paging information in your model! And then you just loop through it

    @foreach(var page in Model.Paging)
    {
       <a href="[email protected]">@page.PageNumber</a> 
    }
    

    And so on.. Get your businesslogic out of your view, that's what MVC promotes, clean seperation! :)

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 09, 2013 @ 16:56
    Sebastiaan Janssen
    0

    Totally hijacked this thread by the way, sorry Kieron!! :-)

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 09, 2013 @ 16:57
    Martin Griffiths
    0

    heh yeah sorry Kieron! But blooming helpful Seb! Thanks!

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 10, 2013 @ 14:40
    Martin Griffiths
    0

    Hi Seb

    Thanks again for your help on this...Here's what I finally settled on....

    Model

     public class YouTubeModel
      {
        // constants for class
        const string YOUTUBE_CHANNEL = "";
        const string YOUTUBE_DEVELOPER_KEY = "";
        const int PageSize = 5;
    
        // properties for class
        public List<Video> Video { getset; }
        public int TotalPages { getset; }
        public int TotalItems { getset; }
        public int PageIndex { getset; }
    
        // constructor for class
        public YouTubeModel(int pageIndex)
        {
          // Google video feed settings
          YouTubeRequestSettings settings = new YouTubeRequestSettings("Staging Youtube", YOUTUBE_DEVELOPER_KEY);
          YouTubeRequest request = new YouTubeRequest(settings);
    
          // set up the url to feed
          string feedUrl = String.Format("http://gdata.youtube.com/feeds/api/users/{0}/uploads?orderby=published", YOUTUBE_CHANNEL);
    
          // create a feed list of Google.YouTube.Video
          Feed<Video> videoFeed = request.Get<Video>(new Uri(feedUrl));
    
          // populate paging properties
          TotalPages = (int)Math.Ceiling((double)videoFeed.Entries.Count() / (double)PageSize);
          TotalItems = videoFeed.Entries.Count();
    
          // check upper and lower boundaries and set page index property accordingly
          PageIndex = pageIndex > TotalPages ? TotalPages : pageIndex;
          PageIndex = pageIndex < 1 ? 1 : PageIndex;
    
          // select list of videos based on current page index
          Video = videoFeed.Entries.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();
        }
      }

    Controller

    public class YouTubeController : SurfaceController
      {
        public ActionResult YouTube(int page = 1)
        {
          //we will create a custom model
          YouTubeModel vm = new YouTubeModel(page);
          return PartialView("YouTube", vm);
        }
      }

    View snippet

    <div class="result">
    @foreach (var item in Model.Video)
    {
      var duration = TimeSpan.FromSeconds(Convert.ToDouble(item.Media.Duration.Seconds)).ToString();
      <div class="team_member_container">
        <div class="one_third_column">
          <p>
            <img class="youtube" id="@item.Media.VideoId.Value" src="@item.Media.Thumbnails[1].Url" alt="@item.Title" style="width100%cursorpointermargin0 10px 0 0" />
          </p>
        </div>
        <div class="two_thirds_column">
          <p><strong><a class="youtube" id="@item.Media.VideoId.Value" href="#">@item.Title</a></strong></p>
          <p><strong>Duration:</strong> @duration</p>
          <p><strong>Published:</strong> @item.AtomEntry.Published.Date.ToShortDateString()</p>
          <p>@item.Description</p>
        </div>
      </div>
    }
    </div>
    <div class="pager_bar">
      <div class="prev grid_2">
        <a href="?page=@prev">Previous</a>
      </div>
      <div class="pages grid_8">
        <ul class="paging">
          @for (int p = 1; p < Model.TotalPages + 1; p++)
          {
            string selected = (p == Model.PageIndex) ? "current no_link" : String.Empty;
            <li class="@selected"><a href="?page=@p" title="Go to page @p of results">@p</a></li> 
          }
        </ul>
      </div>
      <div class="next grid_2">
        <a href="?page=@next">Next</a>
      </div>
    </div>

    Thanks again, much tidier and closer to best practice methinks!

    M.

     

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 10, 2013 @ 19:30
    Sebastiaan Janssen
    0

    Awesome Martin, looking good, glad you got it all working together so nicely. I would populate the duration in your controller as well and the ToShortDateString too, but other then that it looks great!

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 11, 2013 @ 10:18
    Martin Griffiths
    0

    Hi Seb

    I wasnt entirely sure how to do that as it's part of the YouTube object model and it's built into a list.

    M.

  • Martin Griffiths 826 posts 1269 karma points c-trib
    Oct 11, 2013 @ 11:26
    Martin Griffiths
    1

    @Seb

    Had another quick thunk and decided to wrap another simple class just around the bits of information I needed from the YouTube API from which I could build a list.

      public class YouTubeFeed
      {
        public string VideoId { getset; }
        public string Thumbnail { getset; }
        public string Title { getset; }
        public string Duration { getset; }
        public string Published { getset; }
        public string Description { getset; }
      }

    This meant I could take out the two other bits of code in the view that were doing conversions and I ended up with this in the model...

      public class YouTubeModel
      {
        // constants for class
        const string YOUTUBE_CHANNEL = "";
        const string YOUTUBE_DEVELOPER_KEY = "";
        const int PageSize = 5;
    
        // properties for class
        public List<YouTubeFeed> Video { getset; }
        public int TotalPages { getset; }
        public int TotalItems { getset; }
        public int PageIndex { getset; }
        public IPublishedContent Content { getset; }
    
        // constructor for class
        public YouTubeModel(int pageIndex)
        {
          // Google video feed settings
          YouTubeRequestSettings settings = new YouTubeRequestSettings("Staging Youtube", YOUTUBE_DEVELOPER_KEY);
          YouTubeRequest request = new YouTubeRequest(settings);
    
          // set up the url to feed
          string feedUrl = String.Format("http://gdata.youtube.com/feeds/api/users/{0}/uploads?orderby=published", YOUTUBE_CHANNEL);
    
          // create a feed list of Google.YouTube.Video
          Feed<Video> videoFeed = request.Get<Video>(new Uri(feedUrl));
    
          // populate paging properties
          TotalPages = (int)Math.Ceiling((double)videoFeed.Entries.Count() / (double)PageSize);
          TotalItems = videoFeed.Entries.Count();
    
          // check upper and lower boundaries and set page index property accordingly
          PageIndex = pageIndex > TotalPages ? TotalPages : pageIndex;
          PageIndex = pageIndex < 1 ? 1 : PageIndex;
    
          // select list of videos based on current page index
          Video = (from video in videoFeed.Entries
                   select new YouTubeFeed() { VideoId = video.VideoId, 
                                              Title = video.Title,
                                              Duration = ConvertSecondsToMinutes(video.Media.Duration.Seconds),
                                              Thumbnail = String.Format("http://img.youtube.com/vi/{0}/mqdefault.jpg", video.VideoId),
                                              Description = video.Description,
                                              Published = video.Updated.ToShortDateString()
                                            }).Skip((PageIndex -1) * PageSize).Take(PageSize).ToList();
        }
    
        // simple method to convert seconds to time
        private static string ConvertSecondsToMinutes(string seconds)
        {
          return TimeSpan.FromSeconds(Convert.ToDouble(seconds)).ToString();
        }
      }
    

    Now the view is very clean!

    Thanks for your help.

    Martin.

  • Sebastiaan Janssen 5045 posts 15477 karma points MVP admin hq
    Oct 11, 2013 @ 13:08
    Sebastiaan Janssen
    0

    Sweet! You've just discovered the concept of ViewModels! :-)

  • Kieron McIntyre 116 posts 359 karma points
    Oct 23, 2013 @ 12:54
    Kieron McIntyre
    0

    Hi Seb,

    Just wanted to say thanks - I took the leap and started converting my project. I can actually start seeing some light at the end of the tunnel. Sure, I'm going to have to retain a masterpage for one template but I will be able top replace this with time

    @kieron Yeah the webforms are going to be a problem and I would not want to maintain two "master" layouts! :(

    "just" convert the webforms to MVC man, you know you want to! ;-) disclaimer: just messing with you.. :)

    It took a few hours and there'll be some more from testing but worth it.

Please Sign in or register to post replies

Write your reply to:

Draft