0

Guys i want to create a simple APP where users can post whatever text they want, something with a title and a body. The thing is that i want to make it private with authentication in a way that i can see only the posts that i made using my email and password, to achieve that authentication i planned on using Identity.

This is the model that i want to represent:

enter image description here

I tried to do it in C# code and got this: enter image description here

Is that model code okay for what i want to do?

Here is my ApplicationDbContext:

enter image description here

If it´s not that much of an effort i would like an example for create a new post for a logged in user and then display the posts that that user made.

Thanks!

  • Take a look at the MVC tutorial. Should have everything you are looking for to get started. https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/controller-methods-views?view=aspnetcore-5.0 – LinkedListT Jan 18 '21 at 02:22
  • You can get current user like this question https://stackoverflow.com/questions/38751616/asp-net-core-identity-get-current-user/38751842 and then get/update the posts – matmahnke Jan 18 '21 at 02:28
  • other way is filter Posts directly by UserId – matmahnke Jan 18 '21 at 02:28
  • 2
    I know taking screenshot is easier but it does not help searching machines to discover the code text (which will be searched by someone else). Type code instead, you may have just to copy your code and modify a bit (if you want to hide the exact code). – King King Jan 18 '21 at 10:04
  • 1
    It's highly advisable to decouple authentication and business logic, i.e. have your own User class/table for the application that only points to the IdentityUser. But this is a broad/opinion-based question, which is off-topic on Stack Overflow. – Gert Arnold Jan 19 '21 at 07:52

1 Answers1

2

Here is a whole working demo you could follow:

Model:

public class User:IdentityUser
{
    public List<Post> Posts { get; set; }
}
public class Post
{
    [Key]
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
    [ForeignKey("User")]
    [MaxLength(450)]
    public string UserId { get; set; }
    public User User { get; set; }
}

Index.cshtml:

@model IEnumerable<Post>
<h1>Index</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Title)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Body)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.User)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Title)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Body)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.User.Id)
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.PostId">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.PostId">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.PostId">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

Create.cshtml:

@model Post

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Post</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Body" class="control-label"></label>
                <input asp-for="Body" class="form-control" />
                <span asp-validation-for="Body" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Controller:

public class PostsController : Controller
{
    private readonly ApplicationDbContext _context;
    private readonly UserManager<User> _userManager;
    public PostsController(ApplicationDbContext context,UserManager<User> userManager)
    {
        _context = context;
        _userManager = userManager;
    }

    // GET: Posts
    public async Task<IActionResult> Index()
    {
        var applicationDbContext = _context.Posts.Include(p => p.User)
                                                .Where(a=>a.User.UserName==User.Identity.Name);
        return View(await applicationDbContext.ToListAsync());
    }
    // GET: Posts/Create
    public IActionResult Create()
    {
        return View();
    }

    // POST: Posts/Create
    // To protect from overposting attacks, enable the specific properties you want to bind to, for 
    // more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(Post post)
    {
        var user = _userManager.FindByNameAsync(User.Identity.Name).Result;
        post.UserId = user.Id;
        if (ModelState.IsValid)
        {
            _context.Add(post);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(post);
    }
}

Be sure update your _LoginPartial.cshtml:

@using Microsoft.AspNetCore.Identity
@inject SignInManager<User> SignInManager
@inject UserManager<User> UserManager

Be sure update your Startup.cs:

services.AddDefaultIdentity<User>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

Result:

enter image description here

Rena
  • 30,832
  • 6
  • 37
  • 72
  • That helped me a lot to understand how identity and binding items to int works. Thanks a lot! I have one question about using `@Html.DisplayFor`, why do you use it instead of manually writing Title, Body, User? and in the loop the `@Html.DisplayFor` instead of @item. – Agus Mariscotti Jan 19 '21 at 21:02
  • Of corese you can manually add table header.For using html helper,just the default scarffold code. – Rena Jan 20 '21 at 01:39