Skip to content

Instantly share code, notes, and snippets.

@jchadwick
Last active February 9, 2016 20:06
Show Gist options
  • Save jchadwick/0ab56cb4ea5124011152 to your computer and use it in GitHub Desktop.
Save jchadwick/0ab56cb4ea5124011152 to your computer and use it in GitHub Desktop.
Up and Running with ASP.NET 5 - Snippets
/*
* Globals
*/
body {
font-family: Georgia, "Times New Roman", Times, serif;
color: #555;
}
h1, .h1,
h2, .h2,
h3, .h3,
h4, .h4,
h5, .h5,
h6, .h6 {
margin-top: 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: normal;
color: #333;
}
.input-validation-error {
border-color: #a94442;
}
/*
* Override Bootstrap's default container.
*/
@media (min-width: 1200px) {
.container {
width: 970px;
}
}
/*
* Masthead for nav
*/
.blog-masthead {
background-color: #428bca;
-webkit-box-shadow: inset 0 -2px 5px rgba(0,0,0,.1);
box-shadow: inset 0 -2px 5px rgba(0,0,0,.1);
}
/* Nav links */
.blog-nav-item {
position: relative;
display: inline-block;
padding: 10px;
font-weight: 500;
color: #cdddeb;
}
.blog-nav-item:hover,
.blog-nav-item:focus {
color: #fff;
text-decoration: none;
}
/* Active state gets a caret at the bottom */
.blog-nav .active {
color: #fff;
}
.blog-nav .active:after {
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 0;
margin-left: -5px;
vertical-align: middle;
content: " ";
border-right: 5px solid transparent;
border-bottom: 5px solid;
border-left: 5px solid transparent;
}
/*
* Blog name and description
*/
.blog-header {
padding-top: 20px;
padding-bottom: 20px;
}
.blog-title {
margin-top: 30px;
margin-bottom: 0;
font-size: 60px;
font-weight: normal;
}
.blog-description {
font-size: 20px;
color: #999;
}
/*
* Main column and sidebar layout
*/
.blog-main {
font-size: 18px;
line-height: 1.5;
}
/* Sidebar modules for boxing content */
.sidebar-module {
padding: 15px;
margin: 0 -15px 15px;
}
.sidebar-module-inset {
padding: 15px;
background-color: #f5f5f5;
border-radius: 4px;
}
.sidebar-module-inset p:last-child,
.sidebar-module-inset ul:last-child,
.sidebar-module-inset ol:last-child {
margin-bottom: 0;
}
/* Pagination */
.pager {
margin-bottom: 60px;
text-align: left;
}
.pager > li > a {
width: 140px;
padding: 10px 20px;
text-align: center;
border-radius: 30px;
}
/*
* Blog posts
*/
.blog-post {
margin-bottom: 60px;
}
.blog-post .title {
margin-bottom: 5px;
font-size: 40px;
}
.blog-post .meta {
margin-bottom: 20px;
color: #999;
}
.blog-post .comment {
border: 1px solid rgba(0,0,0,.1);
padding: .5em;
margin: .5em;
font-size: 80%;
}
.blog-post .comment .details {
font-size: 80%;
color: #999;
}
/*
* Footer
*/
.blog-footer {
padding: 40px 0;
color: #999;
text-align: center;
background-color: #f9f9f9;
border-top: 1px solid #e5e5e5;
}
.blog-footer p:last-child {
margin-bottom: 0;
}
$(function () {
$(document).on('click', '.show-comments', function (evt) {
evt.stopPropagation();
new Post(this).showComments();
return false;
});
$(document).on('click', '.add-comment', function (evt) {
evt.stopPropagation();
new Post(this).showAddComment();
return false;
});
$(document).on('submit', '.new-comment form', function (evt) {
evt.stopPropagation();
new Post(this).addComment();
return false;
});
});
function Post(el) {
var $el = $(el),
postEl = $el.hasClass('blog-post') ? $el : $el.parents('.blog-post'),
postId = postEl.data('post-id'),
addCommentEl = postEl.find('.add-comment'),
newCommentEl = postEl.find('.new-comment'),
commentEl = newCommentEl.find('[name=Body]'),
commentsContainer = postEl.find('.comments-container'),
commentsEl = postEl.find('.comments'),
showCommentsButton = postEl.find('.show-comments'),
noCommentsEl = postEl.find('.no-comments');
return {
addComment: addComment,
renderComment: renderComments,
showAddComment: showAddComment,
showComments: showComments,
};
/********* Public methods ****************/
function addComment() {
var comment = {
PostId: postId,
Body: commentEl.val(),
};
PostCommentService.addComment(comment, renderComments);
}
function showAddComment() {
addCommentEl.addClass('hide');
newCommentEl.removeClass('hide');
commentEl.focus();
}
function showComments() {
PostCommentService.getComments(postId, renderComments);
}
/********* Private methods ****************/
function createCommentElements(comments) {
comments = [].concat(comments);
if (!comments.length) {
return $('<div class="no-comments">No comments</div>');
}
return comments.reduce(function (commentEls, comment) {
var el =
$('<div class="comment">')
.data('comment-id', comment.Id)
.append($('<p class="details">').append(comment.Author || 'Anon').append(' at ' + new Date(comment.PostedDate).toLocaleString()))
.append($('<p class="body">').append(comment.Body));
return commentEls.concat(el);
}, []);
}
function renderComments(comments) {
var commentEls = createCommentElements(comments);
commentsEl.append(commentEls);
commentsContainer.removeClass('hide');
showCommentsButton.remove();
noCommentsEl.remove();
resetAddComment();
}
function resetAddComment() {
addCommentEl.removeClass('hide');
newCommentEl.addClass('hide');
commentEl.val('');
}
}
var PostCommentService = (
function PostCommentService() {
function call(postId, method, onSuccess, data) {
$.ajax({
// RESTful Web API URL: /api/posts/{postId}/comments
url: ['/api/posts', postId, 'comments'].join('/'),
type: method,
data: data,
dataType: 'json',
success: onSuccess
});
}
return {
addComment: function (comment, onSuccess) {
// Add comment by calling URL with POST method and passing data
call(comment.PostId, 'POST', onSuccess, "body=" + encodeUri(comment.Body));
},
getComments: function (postId, onSuccess) {
// Get comments by calling URL with GET method
call(postId, 'GET', onSuccess);
}
};
})();
$(function () {
$(document).on('click', '.show-comments', function (evt) {
evt.stopPropagation();
new Post(this).showComments();
return false;
});
$(document).on('click', '.add-comment', function (evt) {
evt.stopPropagation();
new Post(this).showAddComment();
return false;
});
$(document).on('submit', '.new-comment form', function (evt) {
evt.stopPropagation();
new Post(this).addComment();
return false;
});
});
function Post(el) {
var $el = $(el),
postEl = $el.hasClass('blog-post') ? $el : $el.parents('.blog-post'),
postId = postEl.data('post-id'),
addCommentEl = postEl.find('.add-comment'),
newCommentEl = postEl.find('.new-comment'),
commentEl = newCommentEl.find('[name=Body]'),
commentsContainer = postEl.find('.comments-container'),
commentsEl = postEl.find('.comments'),
showCommentsButton = postEl.find('.show-comments'),
noCommentsEl = postEl.find('.no-comments');
return {
addComment: addComment,
renderComment: renderComments,
showAddComment: showAddComment,
showComments: showComments,
};
/********* Public methods ****************/
function addComment() {
var comment = {
PostId: postId,
Body: commentEl.val(),
};
PostCommentService.addComment(comment, renderComments);
}
function showAddComment() {
addCommentEl.addClass('hide');
newCommentEl.removeClass('hide');
commentEl.focus();
}
function showComments() {
PostCommentService.getComments(postId, renderComments);
}
/********* Private methods ****************/
function createCommentElements(comments) {
comments = [].concat(comments);
if (!comments.length) {
return $('<div class="no-comments">No comments</div>');
}
return comments.reduce(function (commentEls, comment) {
var el =
$('<div class="comment">')
.data('comment-id', comment.Id)
.append($('<p class="details">').append(comment.Author || 'Anon').append(' at ' + new Date(comment.PostedDate).toLocaleString()))
.append($('<p class="body">').append(comment.Body));
return commentEls.concat(el);
}, []);
}
function renderComments(comments) {
var commentEls = createCommentElements(comments);
commentsEl.append(commentEls);
commentsContainer.removeClass('hide');
showCommentsButton.remove();
noCommentsEl.remove();
resetAddComment();
}
function resetAddComment() {
addCommentEl.removeClass('hide');
newCommentEl.addClass('hide');
commentEl.val('');
}
}
var PostCommentService = (
function PostCommentService() {
var commentsHub = $.connection.commentsHub,
onCommentAdded;
/* Listen to server-sent events */
commentsHub.on('commentAdded', function (comment) {
if(onCommentAdded) onCommentAdded(comment);
});
// Initialize connection
$.connection.hub.start();
return {
onCommentAdded: function (callback) {
// Register function to call when comments are added
onCommentAdded = callback;
},
addComment: function (comment, success) {
/* Call server method CommentsHub.NewComment */
commentsHub.server.newComment(comment).done(success);
},
getComments: function (postId, success) {
/* Call server method CommentsHub.GetCommentsByPost */
commentsHub.server.getCommentsByPost(postId).done(success);
}
};
})();
PostCommentService.onCommentAdded(function (comment) {
var selector = ['[data-post-id=',comment.PostId,']'].join('');
new Post($(selector)).renderComment(comment);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Demo blog application to show how to build an ASP.NET 5 application">
<meta name="author" content="Jess Chadwick">
<title>My ASP.NET 5 Blog</title>
<link href="blog.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="blog-masthead">
<div class="container">
<nav class="blog-nav">
<a class="blog-nav-item active" href="#">Home</a>
</nav>
</div>
</div>
<div class="container">
<div class="blog-header">
<h1 class="blog-title">My ASP.NET 5 Blog</h1>
<p class="lead blog-description">Learning ASP.NET 5, one post at a time</p>
</div>
<div class="row">
<div class="col-sm-8 blog-main">
<div class='blog-post'>
<h2 class='title'>
<a href="#">Setting up your development environment</a>
</h2>
<p class='metadata'>
<span>June 18th, 2015</span>
by <a class="author" href='#'>Jess</a>
</p>
<section class="body">
<p>
There are a few things you'll need installed and configured
on your machine before you're able to work with ASP.NET 5:
<ul>
<li>Windows 7 or Windows Server 2008 R2 and above</li>
<li>Visual Studio 2015 (Community Edition or above)</li>
<li>Web Essentials Visual Studio extension</li>
</ul>
</p>
<p>
Once you have those things installed, come on back for the
next blog post and we'll start creating your new project!
</p>
</section>
</div><!-- /.blog-post -->
<div class='blog-post'>
<h2 class='title'>
<a href="#">Welcome to my blog!</a>
</h2>
<p class='metadata'>
<span>June 16th, 2015</span>
by <a class="author" href='#'>Jess</a>
</p>
<section class="body">
<p>Hello, and welcome to my blog!</p>
<p>
I have spent a lot of time curating some of the best information
available on building and maintaining ASP.NET 5 web applications
and I hope you find it useful!
</p>
</section>
</div><!-- /.blog-post -->
<nav class="hide">
<ul class="pager">
<li><a href="#">Previous</a></li>
<li><a href="#">Next</a></li>
</ul>
</nav>
</div><!-- /.blog-main -->
<div class="col-sm-3 col-sm-offset-1 blog-sidebar">
<div class="sidebar-module sidebar-module-inset">
<h4>About</h4>
<p>
This blog is meant for learning, and that's just what we'll do.
One of these days, this blog is gonna learn all over you.
</p>
</div>
<div class="sidebar-module">
<h4>Archives</h4>
<ol class="list-unstyled">
<li><a href="#">March 2014</a></li>
<li><a href="#">February 2014</a></li>
<li><a href="#">January 2014</a></li>
<li><a href="#">December 2013</a></li>
<li><a href="#">November 2013</a></li>
<li><a href="#">October 2013</a></li>
<li><a href="#">September 2013</a></li>
<li><a href="#">August 2013</a></li>
<li><a href="#">July 2013</a></li>
<li><a href="#">June 2013</a></li>
<li><a href="#">May 2013</a></li>
<li><a href="#">April 2013</a></li>
</ol>
</div>
</div><!-- /.blog-sidebar -->
</div><!-- /.row -->
</div><!-- /.container -->
<footer class="blog-footer">
<p>Blog template built for <a href="http://getbootstrap.com">Bootstrap</a> by <a href="https://twitter.com/mdo">@@mdo</a>.</p>
<p>Modified for Lynda.com video training course by <a href="https://github.com/jchadwick">Jess Chadwick</a></p>
<p>
<a href="#">Back to top</a>
</p>
</footer>
</body>
</html>
@inject WebApplication1.Services.FormattingUtility Format
@model WebApplication1.Post
<div class='blog-post' data-post-id="@Model.Id">
<h2 class='title'><a href="@Url.RouteUrl("Post", new { id = Model.Id })">@Model.Title</a></h2>
<p class='metadata'>
<span>@Format.AsDisplayDate(Model.PostedDate)</span>
by <a class="author" href='#'>@Model.Author</a>
</p>
<section class="body">
@Html.Raw(Model.Body)
</section>
<br />
<footer>
<a href="#" class="show-comments">Show Comments</a>
<div class="comments-container hide">
<h3>Comments</h3>
<div class="comments">
</div>
<hr />
<div>
<a href="#" class="add-comment">Add a comment</a>
<div class="new-comment hide">
@using (Html.BeginRouteForm("NewComment", new { postId = Model.Id }))
{
<div class="form-group">
<textarea name="Body" class="new-comment form-control" placeholder="Enter comment here..."></textarea>
<button type="submit" class="btn btn-default">Create Post</button>
</div>
}
</div>
</div>
</div>
</footer>
</div><!-- /.blog-post -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment