<< Previous Post
Next Post >>



Posted by admin under General  Customizations  sBlog.Net v2.0  on Nov 15 2013

In this post, I am going to discuss a method by which you could change how the urls appear when a post's title is clicked. By default the when the title of the post is clicked it appears as "http://sblogproject.net/2013/09/new-theme-published-using-bootstrap". What if you wanted this to appear as "http://sblogproject.net/new-theme-published-using-bootstrap.html"? Here are the steps to do this!

We all love test driven development right? So let me start with changing the unit tests for the post routes.

// Update RouteTests.cs

[TestMethod]
public void Can_Identify_Individual_Post()
{
    var context = new MockHttpContext(0, false, "~/some-post.html");
    var routes = new RouteCollection();
    MvcApplication.RegisterRoutes(routes);
 
    var routeData = routes.GetRouteData(context);
 
    Assert.IsNotNull(routeData);
    Assert.AreEqual("Home", routeData.Values["controller"]);
    Assert.AreEqual("ViewPost", routeData.Values["action"]);
    Assert.AreEqual("some-post", routeData.Values["url"]);            
}
 
[TestMethod]
public void Can_Identify_Individual_Post_With_Status()
{
    var context = new MockHttpContext(0, false, "~/some-post.html/comment-posted");
    var routes = new RouteCollection();
    MvcApplication.RegisterRoutes(routes);
 
    var routeData = routes.GetRouteData(context);
 
    Assert.IsNotNull(routeData);
    Assert.AreEqual("Home", routeData.Values["controller"]);
    Assert.AreEqual("ViewPost", routeData.Values["action"]);
    Assert.AreEqual("some-post", routeData.Values["url"]);
    Assert.AreEqual("comment-posted", routeData.Values["status"]);
}

// Change HomeControllerTests.cs

[TestMethod]
public void Can_Return_Posts_By_URL()
{
    var httpContext = GetHttpContext(false, 0);
    var postController = GetHomeControllerInstance(httpContext);
    postController.ControllerContext = new ControllerContext { HttpContext = httpContext };
    var result = (ViewResult)postController.ViewPost("a-test-url-1", "");
    var model = result.ViewData.Model as ViewPostOrPageModel;
    Assert.IsNotNull(model);
    var post = model.Post;
    Assert.IsNotNull(post);
    Assert.AreEqual("Post Title 1", post.PostTitle);
    Assert.AreEqual(2012, post.PostAddedDate.Year);
    Assert.AreEqual(4, post.PostAddedDate.Month);
}
 
[TestMethod]
public void Can_Return_Posts_By_URL_Private_Owner()
{
    var httpContext = GetHttpContext(true, 1);
    var postController = GetHomeControllerInstance(httpContext);
    postController.ControllerContext = new ControllerContext { HttpContext = httpContext };
    var result = (ViewResult)postController.ViewPost("a-test-url-14", "");
    var model = result.ViewData.Model as ViewPostOrPageModel;
    Assert.IsNotNull(model);
    var post = model.Post;
    Assert.IsNotNull(post);
    Assert.AreEqual("[Private] Post Title 14", post.PostTitle);
    Assert.AreEqual(2012, post.PostAddedDate.Year);
    Assert.AreEqual(4, post.PostAddedDate.Month);
}
 
[TestMethod]
public void Can_Return_Posts_By_URL_Private_Admin()
{
    var httpContext = GetHttpContext(true, 1);
    var postController = GetHomeControllerInstance(httpContext);
    postController.ControllerContext = new ControllerContext { HttpContext = httpContext };
    var result = (ViewResult)postController.ViewPost("a-test-url-11", "");
    var model = result.ViewData.Model as ViewPostOrPageModel;
    Assert.IsNotNull(model);
    var post = model.Post;
    Assert.IsNotNull(post);
    Assert.AreEqual("[Private] Post Title 11", post.PostTitle);
    Assert.AreEqual(2012, post.PostAddedDate.Year);
    Assert.AreEqual(4, post.PostAddedDate.Month);
}        
 
[TestMethod]
[ExpectedException(typeof(UrlNotFoundException), "Unable to find a post w/ the url a-test-url-25 for the month 01 and year 2012")]
public void Can_Throw_Appropriate_Exception_When_Accessing_Private_Post()
{
    var httpContext = GetHttpContext(true, 1);
    var postController = GetHomeControllerInstance(httpContext);
    postController.ControllerContext = new ControllerContext { HttpContext = httpContext };
    var result = (ViewResult)postController.ViewPost("a-test-url-25", "");
    var model = result.ViewData.Model as ViewPostOrPageModel;
    Assert.IsNotNull(model);
    var post = model.Post;
}
 
[TestMethod]
[ExpectedException(typeof(UrlNotFoundException), "Unable to find a post w/ the url a-test-url-10 for the month 04 and year 2012")]
public void Can_Return_Posts_By_URL_Private_Non_Admin()
{
    var httpContext = GetHttpContext(true, 2);
    var postController = GetHomeControllerInstance(httpContext);
    postController.ControllerContext = new ControllerContext { HttpContext = httpContext };
    var result = (ViewResult)postController.ViewPost("a-test-url-10", "");
    var model = result.ViewData.Model as ViewPostOrPageModel;
    Assert.IsNotNull(model);
    var post = model.Post;
}

Next, the route definition for an individual post has to be updated in order to modify the url format as shown below:

routes.MapRoute("IndividualPost", "{url}.html/{status}",
                new { controller = "Home", action = "ViewPost", status = UrlParameter.Optional },
                new { url = @"\S+", status = @"[a-z\-]*" });

If you notice, the value for action has been changed to "ViewPost" from "View". Now the controller has to be updated to take care of these changes. To begin with I have change the method name to ViewPost. Then this action method is not going to receive the year and the month any more, but only the url (and optionally status). Here is the updated action method.

public ActionResult ViewPost(string url, string status)
{
    var allPosts = GetPostsInternal();
    var currentPost = allPosts.SingleOrDefault(p => p.PostUrl == url && p.EntryType == 1);
 
    if (currentPost == null)
    {
        throw new UrlNotFoundException("Unable to find a post w/ the url {0}", url);
    }

    // -- Cut for brevity --     

    return View(model);
}

The next step is to change the file name of sBlog.Net\Views\Home\View.cshtml to ViewPost.cshtml. And here is the updated content for this file.

@model sBlog.Net.Models.ViewPostOrPageModel
 
@if (Model.PreviousPost != null)
{
    <div style="float: left">
        @Html.RouteLink("<< Previous Post", "IndividualPost", new { url = Model.PreviousPost.PostUrl, status = string.Empty }, new { @title = Model.PreviousPost.PostTitle })
    </div>
}
 
@if (Model.NextPost != null)
{
    <div style="float: right">
        @Html.RouteLink("Next Post >>", "IndividualPost", new { url = Model.NextPost.PostUrl }, new { @title = Model.NextPost.PostTitle })
    </div>
}

Finally, update the sBlog.Net\Views\Shared\Post.cshtml file to present the new url format for the title link for the post.

<div class="post">
    @{
        var url = Url.RouteUrl("IndividualPost", new { url = Model.Post.PostUrl, status = string.Empty });
    }
    
    ....
    
</div>

Hope this post was interesting! If you do have any questions/ comments post them here!

share the love!



comments


comment awaiting moderation
i'm gonna try this one

posted by flower at 3/14/2016 6:39:05 PM


comment awaiting moderation
asdf

posted by afdk at 11/2/2015 5:15:15 PM


vry gd

posted by aksjaksj at 7/15/2014 8:42:55 AM




post your comment

name (*) - required
email address (*) - required
site address
your comment (*) - required

(*) - required


<< Previous Post
Next Post >>