Giter VIP home page Giter VIP logo

blogtemplate's Introduction

ASP.NET Core Blog Template

We created this blog template for Visual Studio to help users create a new, personal web application quickly and effortlessly.


Deprecated Please use Miniblog.Core as an example of an ASP.NET Core blog template.


This is a blogging engine based on Razor Pages and ASP.NET.

Live demo: https://venusblog.azurewebsites.net/

Username: [email protected]

Password: Password.1

Introduction to the Blog Template

This blog template is meant to help developers building a blog or a different web app that includes any features from this template. In using our blog, developers will save time because they can use this template to work from and build off of. This blog template also provides a fresh look at building web apps from ASP.NET Core using the new Razor Pages architecture. If you're not aware of Razor Pages yet, you should take a look as it effectively streamlines building a web application by associating HTML pages with their code so rather than compartmentalizing a project by the model-view-controller pattern, the separation is made by each additional page. We have found this very easy to work with because it allows us to think of the project by the components that make it up rather than the type of each component.

We believe that a blog template can appeal to the broadest audience of developers while also providing an opportunity for us to show off a variety of unique and handy features. If we are already using the newest tools provided by the Visual Studio team at Microsoft, it felt appropriate to use the newest architecture (Razor Pages) for the project. With a blog, we could also appeal to those developers interested in building ecommerce, photo gallery, or a personal web site because all three alternatives are simply variations of a blog with authentication. This makes the basic structure of the template useful for a wider variety of developers than only those interested in building a blog.

A more detailed talk we did on writing the blog template with code reviews and demos is available here.

Background

This template was designed to help Visual Studio users create new web applications fast and effortlessly. We decided on building a Blog Template because such a template would give developers (with varying levels of experience) the ability to create a simple project, and add as much complexity to it as they wanted. The additional features to the blog are what make it a useful tool for developers:

  • Entity Framework provides an environment that makes it easy to work with relational data. In our scenario, that data comes in the form of blog posts and comments for each post.
  • The usage of LINQ (Language Integrated Query) enables the developer to store (query) items from the blog into a variety of targets like databases, xml documents (currently in use), and in-memory objects without having to redesign how things are queried, but rather where they are stored.
  • The blog is built on Razor Pages from ASP.NET Core. Because of this, developers with some knowledge of ASP.NET Core can learn about the pros and cons of building with Razor Pages as opposed to the previously established MVC schema.
  • The template includes a user authentication feature, done by implementing the new ASP.NET Identity Library for Razor Pages. This was a simple tool to add that consisted of installing the NuGet package and creating a new project with the package and then transferring the previous project files into this new project with Identity. Although a hassle, moving the files from one project to the other was quite simple because both projects were built with Razor Pages.
  • Customizing the theme is fast and flexible with the use of Bootstrap. Simply download a Bootstrap theme.min.css file and add it to the CSS folder in your project (wwwroot > css). You can find free or paid Bootstrap themes at websites such as bootswatch.com. You can delete our default theme file, journal-bootstrap.min.css, to remove the default theming. Run your project, and you'll see that the style of your blog has changed instantly.

Goals

We hope the above features make this a tool that developers can use to speed up the development process of their project while also serving an educational purpose for those who want to learn how to implement/work with those new items. In making this an educational tool, we hope that our blog provides effective examples of said features. The following are a set of goals that we attempted to achieve and we challenge you to accomplish on your way to building the best web applications: * Grow ASP.NET Core usage * Educate users about Razor Pages * Grow Visual Studio usage * Build a community around the template

Using the Template

Creating an Instance of the Template (Your Own Blog)

There are two options for instantiating a template. You can use dotnet new included with the dotnet CLI and go dotnet new -i c:\pathtothecloneofthisrepo. However, the current version contains minor bugs that will be fixed soon. Alternatively, you'll need to get the newest templating code with the following steps. Click the green "Clone or download" button. Copy the link in the dropdown that appears. Open a command prompt and change directories to where you want to install the templating repo. In the desired directory, enter the command:

git clone [link you copied earlier]

This will pull all the dotnet.templating code and put it in a directory named "templating." Now change to the templating directory and switch branches to "rel/2.0.0-servicing" by running:

git checkout rel/2.0.0-servicing

Then run the command setup.

  • Note: If you get errors about not being able to run scripts, close your command window. Then open a powershell window as administrator and run the command Set-ExecutionPolicy Unrestricted. Close the powershell window, then open a new command prompt and go back to the templating directory and run setup again.

Once the setup runs correctly, you should be able to run the command dotnet new3. If you are just using the dotnet CLI, you can replace dotnet new3 with dotnet new for the rest of the steps. Install your blog template with the command:

dotnet new3 -i [path to blog template source]

This path will be the root directory of your blog template repository.

Now you can create an instance of the template by running:

dotnet new3 blog -o [directory you want to create the instance in] -n [name for the instance]

For example:

dotnet new3 blog -o c:\temp\TestBlog\ -n "My Blog"

blogtemplate's People

Contributors

jimmylewis avatar julietdaniel avatar lucasisaza avatar madskristensen avatar mterwoord avatar shanselman avatar umaslakshmi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blogtemplate's Issues

Consider using DateTimeOffset instead of DateTime for storing dates/times

The use of DateTime is prevalent in the codebase:
https://github.com/VenusInterns/BlogTemplate/search?utf8=%E2%9C%93&q=datetime&type=

But, per MSDN, it is preferred to use DateTimeOffset when referring to actual times (i.e. the actual time a blog post was posted, or a comment was commented).

In fact, it goes so far as to say:

Note

These uses for DateTimeOffset values are much more common than those for DateTime values. As a result, DateTimeOffset should be considered the default date and time type for application development.

The change is probably straightforward: just search & replace all DateTime with DateTimeOffset.

Form validation for posts

Posts also need to have their required fields validated

  • Title - Required
  • Post - Required
  • Tags is optional
  • Excerpt is optional

Recommend fields set by ctor that are immutable be marked as 'readonly'

E.g. see https://github.com/VenusInterns/BlogTemplate/blob/master/BlogTemplate/Services/SlugGenerator.cs#L11

This code:

        private BlogDataStore _dataStore;

Should be:

        private readonly BlogDataStore _dataStore;

This ensures that the _dataStore field can't be overwritten anywhere else. The readonly modifier indicates that the field can be set from only the constructor.

I recommend checking elsewhere in the code in case this same recommendation applies anywhere else.

Limit Registration to one user

Our blog should only allow one person to register as a user, that way everyone else that visits the blog is a guest and cannot edit/write posts.

New Post > Title - special characters not handled correctly

Repro:
Enter the following form fields:
Title: punctuation in slugs?
Your post...: huh
Excerpt: huh
Tags: idk

Expected:
Special characters are removed from the slug (in the slug generator method).

Actual:
Throw an Exception User-Unhandled

System.ArgumentException: 'Illegal characters in path.'

The singleton 'Blog' service is not thread-safe

In Startup.cs a singleton 'Blog' service is registered:

https://github.com/VenusInterns/BlogTemplate/blob/master/BlogTemplate/Startup.cs#L48

But the implementation of the Blog class is clearly not thread-safe for multiple writers:

https://github.com/VenusInterns/BlogTemplate/blob/master/BlogTemplate/Models/Blog.cs#L11-L13

That is, if two threads (e.g. two requests) both call Blog.Comments.Add(...) at the same time, something "bad" will happen.

For example, see this code here: https://github.com/VenusInterns/BlogTemplate/blob/master/BlogTemplate/Pages/New.cshtml.cs#L70

Preview Post

Preview the post after editing it and before actually publishing it to the site.

Can't post new blog entry unless you first go to the /Index page to "load" the blog posts

I haven't actually tried it, but I'm certain it will happen:

  1. Launch the site, but do not visit the / (or /Index) page!
  2. Browse to the /New page and type in your awesome new blog post
  3. Press the Save button (doesn't matter whether it's Public or Draft)

Result: I'm guessing that this line will throw a null ref exception:

_blog.Posts.Add(Post);

Why? Because the only thing that seems to "load" the blog posts is the /Index page here:

_blog.Posts = _dataStore.GetAllPosts();

While this bug is trivial to fix, I think there's a bit of a mismatch between how the singleton Blog service is used, and how the IDataStore is used. It isn't clear from the code what is the responsibility of each - in fact, it seems like they both share certain responsibilities, which is apparent in this code, where when a new post is added, two different data structures need to be modified. (This is also orthogonally related to #47.)

I'm happy to discuss this in person if anything here wasn't clear.

Where do drafts go?

I made a post and clicked Save Draft. Nothing happened? Unclear from the UI if it's gone or not.

Remove "Make public" checkbox

In the following files:

  • New.cshtml
  • Edit.cshtml

Might therefore need to change functionality slightly in New.cshtml.cs and Edit.cshtml.cs

Save DateTimes in ISO8601

Never save dates in a "culture specific" format. Always use ISO8601 as a culture invariant. You deserailize the date from that format and THEN output it specific to the user's machine in the view.

Slug Generator Test

The test for SlugGenerator about removing invalid characters in the title is failing.

Drafts page should display posts in the same form as the Index page

Currently the drafts page doesn't include the number of comments on the post or the date of the post. If it has already been published and then saved to drafts we should outline the date. In other cases where the post has yet to be published there should be nothing in that space.

Cancel Button looses purpose

When the logged in user goes to drafts and selects a draft he/she is taken to the edit page of that post. However, there is a small cancel button at the bottom that when pressed just takes you back to the previous page. I think this button may not be necessary in this scenario since you could just use the arrows to go back.

Error with New Post

Cannot write a new post. When clicked it says "An error occurred during the compilation of a resource required to process this request. Please review the following specific error details and modify your source code appropriately."

Recommend using "separation of concerns" for viewing lists of posts and whether they are public or draft

Currently the Index page and Drafts page both have the same "model" behavior: the model retrieves all blog posts, regardless of their visibility state (public or draft).

Then the view pages have their own logic for filtering the posts: when they enumerate the full list of posts, they apply some (simple) filtering logic to determine which subset of posts to show.

Instead of that, the views should not know what kind of posts they are showing: they should be provided with an already-filtered list of posts, and then they can iterate over them. You want "smart" models and "dumb" views in general.

Here are the "offending" lines:

I recommend that instead of the models doing this:

            _blog.Posts = _dataStore.GetAllPosts();

That they do something like this:

            _blog.PublicPosts = _dataStore.GetAllPosts().Where(post => post.IsPublic);

And then the views get "dumber" and instead of this:

    foreach (var post in Model.Posts)
    {
        if (!post.IsPublic)
        {

Do something like this:

    foreach (var post in Model.PublicPosts)
    {

Characters not accepted as the title

The following characters alone or repeated 'break' the slug so that once you publish or save the draft, you cannot access it since the character title seems to break the slug. Those characters are: '#', '/', '', '|', '<', '>'

Similarly, if the title of the post is '%' then we get a BadRequest 400 error 'Invalid URL'.

The SlugGenerator isn't really a "service"

The SlugGenerator is new'ed up wherever it's used, e.g.:

  1. SlugGenerator slugGenerator = new SlugGenerator(_dataStore);
  2. SlugGenerator slugGenerator = new SlugGenerator(_dataStore);

It would be more typical to register the SlugGenerator as an actual service in Startup.cs's ConfigureService method, and then consume it from the DI container wherever it's used.

If you haven't used this pattern before, your friendly local Ryan (e.g. @rynowak) or Taylor (@NTaylorMullen) can help you do this in Razor Pages.

Edit Post: old slug vs. new slug

Repro:
Edit title of an existing post

Expected:
Old slug will still work as a link

Actual:
New slug is generated and replaces old slug, therefore breaking any external links to the post

Possible solution:
Warn user that external links could break, allow them to keep old slug?

Using commas to separate tags not working; throwing an exception

To reproduce:
Write a new post. Enter the following fields:
Title: panda panda panda
Your post...: I got broads in Atlanta
Excerpt: I got broads in Atlanta
Tags: broads,atlanta

Expected:
Redirects to the Index and displays the new post at the top, showing Title, PubDate, Excerpt, and Tags.

Actual:
In New.cshtml.cs, line 66 throws an exception whenever commas are entered in the tags field.

Exception User-Unhandled
System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.