views:

158

answers:

3

I am Java developer new to .NET. I am working on a .Net MVC2 project where I want to have a partial view to wrap a widget. Each JS widget object has a JSON data object that would be populated by the model data. Then methods to update this data bound to events when data is changed in the widget or if that data is changed in another widget. The code is something like this.

MyController

virtual public ActionResult DisplaySomeWidget(int id)
            {
                SomeModelView returnData = someDataMapper.getbyid(1);

                return View(myview, returnData);
            }

myview.ascx

 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SomeModelView>" %>

            <script type="text/javascript">

                //creates base widget object;
                var thisWidgetName= new Widget();

                thisWidgetName.updateTable= function() {
                  //  UpdatesData
                };

                    $(document).ready(function () {
                        thisWidgetName.data = <% converttoJSON(model) %>
                        $(document).bind('DATA_CHANGED',  thisWidgetName.updateTable());
                    });
                </script>

            <div><%:model.name%></div>

What I don't know is how to send the data over as SomeModelView and then be able to use that to populate the widget as well as convert that to Json. I had seem some real simple ways to do it in the controller but not in the view. I figure this is a basic question bu I've been going for a few hours trying to make this slick.

+1  A: 

you can use Json from the action direct,

you action would look something like

virtual public JsonResult DisplaySomeWidget(int id)
            {
                SomeModelView returnData = someDataMapper.getbyid(1);

                return Json(returnData);
            }

edit

just seen that you assume that this is the Model of a View so the above isnt strictly correct, you would have to make an Ajax call to the controller method to get this, the ascx would not then have a model per se, I will leave my code in just in case it is useful to you and you can ammend the call

Pharabus
but he cant render this into the view, he'd have to make a 2nd ajax call
Andrew Bullock
@Andrew Bullock just edited once i realised
Pharabus
Thanks, I was originally doing this using a jQuery get json call and was planning on having the HTML elements populate them selves from json. However, the pattern we are following right now is that our views should return a modelView and that is the easiest way to populate basic HTML elements like tables etc. I could send over the same data in JSON format as ViewData but it seems wasteful.
Chris
+1  A: 

well done, youve only just started using MVC and youve found its first major flaw.

You don't really want to be converting it to JSON in the view, and you dont really want to convert it in the controller, as neither of these locations make sense. Unfortunately, youre stuck with this situation.

The best thing I've found to do is send the JSON to the view in a ViewModel, like this:

var data = somedata;
var viewModel = new ViewModel();
var serializer = new JavaScriptSerializer();
viewModel.JsonData = serializer.Serialize(data);

return View("viewname", viewModel);

then use

<%= Model.JsonData %>

in your view. Be aware that the standard .NET JavaScriptSerializer is pretty crap.

doing it in the controller at least makes it testable (although no exactly like the above, you probably want to take an ISerializer as a dependency so you can mock it)

Update also, in reference to your javascript, it would be good practice to wrap ALL the widget JS you have above like so:

(
    // all js here
)();

this way if you put multiple widgets on a page, you wont get conflicts (unless you need to access the methods from elsewhere in the page, but in that case you should be registering the widget with some widget framework anyway). It may not be a problem now, but it would be good practice to add the brackets now to save yourself muchos effort in the future when it becomes a requirement, its also good OO practice to encapsulate the functionality.

Andrew Bullock
This looks interesting. I was going to just make a copy of the data as json and pass it as viewData but this way it looks more interesting. I'll play with this and let you know. BTW this is my first time posting a question on stackoverflow and it took what..5 minutes to get good responses, that is awesome!!
Chris
What's wrong with `JavaScriptSerializer`?
Crescent Fresh
nothings _wrong_ with it, its just not customisable, if you want any custom value formatting you have to do it before hand, basically making everything a string :( this is most prominent with dates. i know there are easy workarounds, but they shouldnt be necessary!
Andrew Bullock
@Update I was going see about using a .net static counter of that widget to generate a unique object name. But what you wrote looks like it would accomplish the same thing and do it slicker. Also I did look into binding the creation of a widget "new_widget_event' to a page level object to track them but the original reason for doing that became OBE. So I might revisit that later. thanks for all the help I'm going to post a modified version of what you suggested but put explain why I like it better.
Chris
A: 

Andrew had a great response but I wanted to tweek it a little. The way this is different is that I like my ModelViews to not have overhead data in them. Just the data for the object. It seem that ViewData fits the bill for over head data, but of course I'm new at this. I suggest doing something like this.

Controller

virtual public ActionResult DisplaySomeWidget(int id)
            {
                SomeModelView returnData = someDataMapper.getbyid(1);
                var serializer = new JavaScriptSerializer();
                ViewData["JSON"] = serializer.Serialize(returnData);
                return View(myview, returnData);
            }

View

   //create base js object;
    var myWidget= new Widget(); //Widget is a class with a public member variable called data.
    myWidget.data= <%= ViewData["JSON"] %>;

What This does for you is it gives you the same data in your JSON as in your ModelView so you can potentially return the JSON back to your controller and it would have all the parts. This is similar to just requesting it via a JSONRequest however it requires one less call so it saves you that overhead. BTW this is funky for Dates but that seems like another thread.

Chris