Producenta
Producenta

Reputation: 649

How to send data from view to controller

I am making my first asp.net mvc project forum system. I am trying to add post but i don't know how to send data from view to controller. I have viewmodels that i am using, but i want to send current threadId to post action and to write it in database. Here is my code:

 public ActionResult Create(CreatePostInputModel input)
    {
        if (ModelState.IsValid)
        {
             var content = sanitizer.Sanitize(input.Content);

             var post = new Post
             {
                 ThreadId = ViewBag.ThreadId,
                 AuthorId = this.User.Identity.GetUserId(),
                 Content = content,
                 IsDeleted = false,
                 CreatedOn = DateTime.Now,
                 PreserveCreatedOn = true
             };

             this.Data.SaveChanges();

            this.RedirectToRoute("Show thread", new {id = post.ThreadId, name = post.Thread.Title });
        }



public class PostViewModel : IMapFrom<Data.Models.Post>, IHaveCustomMappings
{
    public PostViewModel()
    {
        this.CreatePostInputModel = new CreatePostInputModel();
    }

    public int ThreadId { get; set; }

    public string Title { get; set; }

    public IEnumerable<Data.Models.Post> Posts { get; set; }

    public CreatePostInputModel CreatePostInputModel { get; set; }

    public void CreateMappings(IConfiguration configuration)
    {
        configuration.CreateMap<Data.Models.Post, PostViewModel>()
            .ForMember(m => m.Title, opt => opt.MapFrom(t => t.Thread.Title))
            .ForMember(m => m.ThreadId, opt => opt.MapFrom(t => t.ThreadId));

        configuration.CreateMap<Thread, PostViewModel>()
            .ForMember(m => m.Posts, opt => opt.MapFrom(t => t.Posts))
                .ReverseMap();

    }
}

my views

@model IEnumerable<ForumSystem.Web.ViewModels.Post.PostViewModel>

    @{
        ViewBag.Title = "Display";
    }

<div class="container">
        @foreach (var thread in Model)
        {
             ViewBag.ThreadId = thread.ThreadId; 
            <div class="row">
                <h4>@thread.Title</h4>
                @foreach (var post in thread.Posts)
                {
                    <div class="col-md-10">
                        <div class="row">
                                <div>@post.Content</div>
                            <span>
                            </span>
                        </div>
                    </div>
                }
             </div>
                <div>
                    @{ Html.RenderPartial("_CreatePartial", thread.CreatePostInputModel); }
                </div>
        }
</div>

Partial view:

@model ForumSystem.Web.InputModels.Post.CreatePostInputModel

@using (Html.BeginForm("Create", "Post", FormMethod.Post, new { @class = "form-horizontal" }))
{
    @Html.AntiForgeryToken()

    @Html.ValidationSummary("", new { @class = "text-danger" })


    <div class="form-group">
        @Html.EditorFor(model => model.Content)
    </div>

    <div class="form-group text-center">
        <input type="submit" value="Добави пост" class="btn btn-primary btn-lg" />
    </div>
}

In CreatePostInputModel I have only one string property Content. I have tried using viewbag, sending parameter from partial view form, but from there i can't get ThreadId. What's the right way to do it? I am thinking of making CreatePostInputModel constructor that takes threadId, but I'am not sure if this is the right way.

Upvotes: 1

Views: 239

Answers (1)

Vsevolod Goloviznin
Vsevolod Goloviznin

Reputation: 12334

You can use a hidden input field to embed the current thread id. You will need to do that inside your form in the partial view.

Your main view:

@model IEnumerable<ForumSystem.Web.ViewModels.Post.PostViewModel>

    @{
        ViewBag.Title = "Display";
    }

<div class="container">
        @foreach (var thread in Model)
        {
             ViewBag.ThreadId = thread.ThreadId; 
            <div class="row">
                <h4>@thread.Title</h4>
                @foreach (var post in thread.Posts)
                {
                    <div class="col-md-10">
                        <div class="row">
                                <div>@post.Content</div>
                            <span>
                            </span>
                        </div>
                    </div>
                }
             </div>
                <div>
                    @{ Html.RenderPartial("_CreatePartial", thread); }
                </div>
        }
</div>

Your partial view:

@modelForumSystem.Web.ViewModels.Post.PostViewModel

@using (Html.BeginForm("Create", "Post", FormMethod.Post, new { @class = "form-horizontal" }))
{
    @Html.AntiForgeryToken()

    @Html.ValidationSummary("", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.ThreadId)

    <div class="form-group">
        @Html.EditorFor(model => model.CreatePostInputModel.Content)
    </div>

    <div class="form-group text-center">
        <input type="submit" value="Добави пост" class="btn btn-primary btn-lg" />
    </div>
}

And in your controller just fetch this id (don't forget to check if the thread with such threadId exists in the DB):

public ActionResult Create(int threadId, CreatePostInputModel input)
{
   if (ModelState.IsValid)
   {
      var content = sanitizer.Sanitize(input.Content);

      var post = new Post
      {
                 ThreadId = threadId,
                 AuthorId = this.User.Identity.GetUserId(),
                 Content = content,
                 IsDeleted = false,
                 CreatedOn = DateTime.Now,
                 PreserveCreatedOn = true
      };

      this.Data.SaveChanges();

      this.RedirectToRoute("Show thread", new {id = post.ThreadId, name = post.Thread.Title });
}

Upvotes: 1

Related Questions