Blog with ASP.NET Core and React/Redux. Part 2: Creating a story

4 min readOct 5, 2018

This is part of the series “Blog with ASP.NET Core and React/Redux”.

Goal for this part

Let’s start the second part of this series by listing features we going to make as user stories.

  1. As a user, I want to be able to write a story so that I will be able to share them with others when publish.
  2. As a user, I want to save and publish a story so that I can share them with others.
  3. As a user, I want to view both drafts and published stories so that I knew what stories I have.
  4. As a user, I want to edit a story so that I can update it.
  5. As a user, I want to delete a story so that I can remove it when I see that peoples don’t like it.

All code for this part you can find in front-end and back-end repositories.


To make this user stories happen, we want our back-end to have endpoints that allow us to work with stories.


For this part, we want one new Entity. We are going to keep the content of the story as JSON string.


Only one new repository for stories.

And we need to update the Story model by adding this field.

public ICollection<Story> Stories { get; set; }

Also, we need to add the method for Story configuration in BlogContext class.


For this part, we need a few new view models.

As we can see, the number of view models increased significantly in comparison with the previous part. And if it will continue this way we will be sick and tired of converting models to view models and back in our controllers. But there is a rescue — AutoMapper.

Let’s create the MappingProfile where we will specify models we want to automap.

Now when we want to make from Story StoryDetailViewModel, we can do it like this.

var storyDetailVM = mapper.Map<StoryDetailViewModel>(story);

Rather than doing it this way:

var storyDetailVM = new StoryDetailViewModel {
Id = story.Id,
Title = story.Title,
Content = story.Content,
Tags = story.Tags,
PublishTime = story.PublishTime,
OwnerId = story.OwnerId,
OwnerUsername = story.Owner.Username

And of course, we need to update ConfigureServices in our Startup class so that we can inject Mapper in our controllers.

var mappingConfig = new MapperConfiguration(mc =>
mc.AddProfile(new MappingProfile())

The final step is to add a controller for stories.

The only thing left, is to update our database by running the migration.


Front-end for this part will consist of three pages:

  1. Editor. The page where we can create a story or edit an existing one.
  2. YourStories. The page where a user can see his drafts and published stories.
  3. Story. The page with published story.


Let’s start with actions for story editor.

Then, let’s create sagas for save and publish actions.

Picture yourself writing a story in a cafe. But suddenly your laptop is out of charge. And since you didn’t push the save button — an article is gone. It sucks! So we are going to make a saga that will trigger save action if something changes.

Reducer for the editor is quite bulky:) So we will not list the whole reducer here.

To implement editor page we need a number of components. Let’s list them.

  • Editor will wrap slate.js component for making reach text editors.
  • EffectsMenu will list possible features of our editor such as making text bold, insert link or make a bulleted list.
  • LinkDialog will allow a user to paste URL of link or image.
  • Mark will specify how to italic, bold or code text.
  • Node as a Mark will render specific elements of the editor, such as lists and headings.
  • Publish and Save will be buttons connected to the state.
  • Title will be the text field for article’s title.
  • TagsDialog will be a component where a user can specify tags for his article.

And the index where everything comes together.


As usual, let’s start with actions.

Next — sagas.

Such simple sagas, but WTF is this?


It is kind of hack that I carry in my js projects. At the start of the app, I run code that will extend the array prototype. You can find it here.

Reducer for this page not even worth the mention:)

Finally, the index of the component.


For now, Story is just a read-only page. And it has only one action.

It doesn’t have saga and reducer is reducer handles only one action.

To render content we will use, previously mentioned Mark, Node components and slate.js library.

In the next part, we will populate our database with mock data. Stay tuned!

Reach the next level of focus and productivity with