Skip to content Skip to sidebar Skip to footer

Viewmodel In Asp.net Mvc

I am trying to create a asp.net mvc site using c#. I have two models an Event model and a Ticket model. I want to be able to create an Event using the supplied CRUD views and then

Solution 1:

Since we have to dynamically add a row for a new ticket, We should be using some javascript to handle the form building and posting.

Create a viewmodel for the Ticket creation page

publicclassCreateTicketVm
{
    publicint EventId { get; set; }
    public List<TicketVm> Tickets { set; get; }
}

publicclassTicketVm
{
    [Required]
    publicstring Description { get; set; }

    [Required]
    publicfloat Price { get; set; }
}

And in the GET action, We will create an object of CreateTicketVm, Set the Event property value and send it to the view.

public ActionResult CreateTicket(int id)
{
    var vm = new CreateTicketVm {EventId = id};       
    return View(vm);
}

And in your view

@model YourNamespace.CreateTicketVm
<div id="tickets"></div>
@Html.HiddenFor(s => s.EventId)

<input type="button" id="add" value="Add Ticket" />
<input type="submit" id="btnSave" />

Now we need to add some javascript to our allow user to create a new ticket row when they click on "Add Ticket" button. Also we will listen to the click event on the submit button and we will build a javascript object which looks same as our CreateTicketVm viewmodel. and we will post (using ajax) the json version of this object to the MVC controller. Once the ticket information is saved, The action method will return a json response which indicates whether the operation was successful. In the done event of the ajax post, we will inspect this response and redirect the usr to the next page(or do some custom thing as needed).

<script>
    $(function () {
       //Lets create the first rowaddNewRow();

        $("#add").click(function (e) {
            e.preventDefault();
            addNewRow();    
        });

        $("#btnSave").click(function (e) {
            e.preventDefault();

            var createTicket = { EventId: $("#EventId").val(), Tickets: [] };
            var rows = $("#tickets").find(".item");

            $.each(rows, function (i, row) {
                var _row = $(this);

                var inputs = _row.find("input");
                var ticket = {};
                $.each(inputs, function (index, item) {
                    var _this = $(this);
                    ticket[_this.data("for")] = _this.val();
                });
                createTicket.Tickets.push(ticket);
            });

            var targetUrl = "@Url.Action("CreateTicket","Home")";
            $.ajax({
                url: targetUrl,
                contentType: "application/json",
                data: JSON.stringify(createTicket),
                type: "POST"
            }).done(function(res) {
                if (res.Status === "Success") {
                    window.location.href = "@Url.Action("Success")";
                }
            });
        });
    });

    functionaddNewRow() {          
        $.get("@Url.Action("AddNewTicketRow","Home")", function (res) {    
            $("#tickets").append(res);    
        });    
    }
</script>

You can see that the addNewRow method is also making an ajax call to get the markup for each ticket row. So let's add an action method for that.

public ActionResult AddNewTicketRow()
{
    var vm = new TicketVm ();
    return PartialView("~/Views/Home/Partials/AddNewTicketRow.cshtml", vm);
}

You can see that we are returning a partial view. So make sure to create the partial view in that location with the below content.

@model TicketVm

<div class="item">
    @Html.TextBoxFor(s => s.Description, new {@data_for = "Description"}) 
    Price : @Html.TextBoxFor(s=>s.Price, new {@data_for="Price"})
</div>

We can build the markup directly in js. But it gets ugly when your markup has more items. So creating a partial view is safe and helps us to easily make markup changes as needed in future.

When user clicks the submit, we are posing the Json version of the object to the CreateTicket HttpPost action method. So let's create that too.

[HttpPost]
public ActionResult CreateTicket([FromBody] CreateTicketVm model)
{
    if (model != null)
    {
       //check model.Tickets and model.EventId// to do : Save Tickets for the eventreturnnew JsonResult( new { Status ="Success"});
    }
    returnnew JsonResult( new { Status ="Error"});
}

The above code is is for Asp.Net MVC 6. In MVC 6, Mvc controllers and Web Api controllers are not separate. They both inherit from Controller class which is in Microsoft.AspNet.Mvc namespace.

If you are using a version prior to MVC 6, You do not need the [FromBody] attribute in your HttpPost action method. Also, for returning json data, you can use Json method.

[HttpPost]
public ActionResult CreateTicket(CreateTicketVm model)
{
    if (model != null)
    {
        //check model.Tickets and model.EventId// to do : Save Tickets for the eventreturn Json(new {Status = "Success"});
    }
    return Json(new {Status = "Error"});
}

Post a Comment for "Viewmodel In Asp.net Mvc"