Pass C# Model from View to Javascript

2019-03-05 06:21发布

问题:

I'm passing this ViewModel to my View:

  public class DashboardViewModel
  {
    public List<UserTask> UserTasks {get; set;}

    public List<WorkItem> WorkItems {get; set;}
  }    

and from within the View I'm iterating through the WorkItems like this:

 @foreach (var item in Model.WorkItems)
 {
    @item.Name
    @item.HoursLogged
    <button value="@item">UPDATE</button>
 }

When I click on the button a jQuery function is opening up a modal.

I need to pass to the modal the item in order to display all the item infos.

This is the javascript function:

$(buttonEl).click(function () {
   //code to open modal
   var item = this.value;
});

The value passed in "this.value" is not an object but a string with the namespace of the WorkItem.

I have also tried with inline onclick function:

<button onclick="openModal('@item')">UPDATE</button>

but with the same result.

Any idea?

回答1:

I normally use this to translate from MVC to javascript!

@Html.Raw(Json.Encode(item))


回答2:

@item in View will print out the item as normal string (item.ToString()). I think what you want is to parse the string as a Javascript object, right?

One approach is to implement a method in your model, like JSON.stringify(). The method can parse the C# model to JSON string:

{
 "Name" : "Scott",
 "HoursLogged" : "2"
}

Then you can parse the string to JSON object in View by using JSON.parse(). In this case, you can use the JSON object. Some thoughts:

C#:

public class Item
{
 public string Name { get; set; }
 public int HoursLogged { get; set; }
 public string ToJsonString()
 {
  return "{" + "\"Name\":" + Name + ",HoursLogged:" + HoursLogged + "}";
 }
}

JS:

var jsonStr = '@item.ToJsonString()';
var jsonObj = JSON.parse(jsonStr);
console.log(jsonObj.Name);
console.log(jsonObj.HoursLogged);

You can also use Newton to stringify C# model.



回答3:

You should store the data you use to loop to a javascript variable and query that when your button is clicked. Keep a unique identifier on your button' data attribute which you can use to query later. Since it is an array, you can simply use a counter variable which matches with the (js) array index.

@{ var counter = 0;}
@foreach (var item in Model.WorkItems)
 {
    @item.Name
    <button class="updateBtns" data-index="@counter">UPDATE</button>
    counter++;
 }

and in the same razor view, have this javascript where you will serialize the Model.WorkItems collection to a javascript array and store it in a variable.

<script>
  $(function() { 

     var dataArr = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.WorkItems));
      $(".updateBtns").click(function (e) {
          e.preventDefault();

          var selectedItem = dataArr[$(this).data("index")];
          console.log(selectedItem);
      });    
  });    
</script>


回答4:

You should probably take a few steps back to understand what is going on here. A web request is really just a bunch of strings, MVC .net does some stuff to try and ease the transition from using objects to just straight string but as you can see it can't do everything. So the take-away is that you to deal with things as if they are all strings when rendered on the page.

That being said there are a number of ways to solve this problem. You can as mentioned before convert all your WorkItem objects to javascript objects and pull them out of the javascript array. Or what I personally like to do is simply have the button contain the id of the object and do an ajax call to get the most recent data from the server.

Back end:

[HttpPost]
public string GetWorkItemById(int id)
{

//get or create WorkItem here
WorkItem workItem = new WorkItem(id);
workItem.Name = "Foobar";
workItem.HoursLogged = "127001";

return Newtonsoft.Json.JsonConvert.SerializeObject(workItem);
}

Front end:

    $(buttonEl).click(function () {    
    var id = this.value; //assuming you store the id in the button's value
    $.ajax({
          type: "POST",
          url: "@(Url.Action("GetWorkItemById"))",
          data: ({
                    Id:id
                 }),
          success: success,
          dataType: dataType, 
          success: function(result){
                var name = result.Name; // Foobar
                var hoursLogged = result.HoursLogged; // 127001
                //populate text fields using jquery
          }
        })
    });