using System; using System.Collections.Generic; using System.Text; using System.Web; using System.Web.UI; using System.Web.Hosting; using System.Web.UI.WebControls; using System.Reflection; using System.Web.Mvc; using System.IO; using Newtonsoft.Json; [assembly: WebResource("jMVCHelper.jMVCplusJson.js", "application/x-javascript")] namespace jMVCHelper { public static class jMVC { private static JsonSerializationHelper s_SerializationHelper = new JsonSerializationHelper(); private static object s_ScriptRegistrationKey = new object(); /// /// Renders the HTML necessary to place a jMVC panel in your page /// /// The host page /// The HTML name of the control (using which you can retrieve the submitted data when the form is posted) /// A JSON-serializable object which acts as the ViewData inside the MVC panel control /// The URL of your jMVC view template (can be application-relative) /// Optional: a Javascript object identifier which will be made available to your view template as 'controller'. public static string MVCPanel(ViewPage viewPage, string name, object viewData, string viewUrl) { return MVCPanel(viewPage, name, viewData, viewUrl, null); } /// /// Renders the HTML necessary to place a jMVC panel in your page /// /// The host page /// The HTML name of the control (using which you can retrieve the submitted data when the form is posted) /// A JSON-serializable object which acts as the ViewData inside the MVC panel control /// The URL of your jMVC view template (can be application-relative) /// Optional: a Javascript object identifier which will be made available to your view template as 'controller'. public static string MVCPanel(ViewPage viewPage, string name, object viewData, string viewUrl, string jsControllerObject) { StringBuilder response = new StringBuilder(); // Add a script reference if needed (since viewPage.ClientScript.RegisterClientScriptResource() doesn't work with MVC) if (!viewPage.ViewContext.HttpContext.Items.Contains(s_ScriptRegistrationKey)) { viewPage.ViewContext.HttpContext.Items.Add(s_ScriptRegistrationKey, true); response.AppendFormat("", viewPage.ClientScript.GetWebResourceUrl(typeof(jMVC), "jMVCHelper.jMVCplusJson.js")); response.AppendLine(); } // Render the viewData as JSON in a hidden INPUT string jsonData = HttpUtility.HtmlEncode(s_SerializationHelper.Serialize(viewData)); response.AppendFormat("", name, jsonData); response.AppendLine(); // Add a DIV to hold the rendered UI string viewDivID = name + "_view"; response.AppendFormat("
", viewDivID); // Create a JS object to hold the model data string viewAbsoluteUrl = GetViewAbsoluteURL(viewUrl); string modelObjectID = name + "_modelobject"; response.AppendLine(""); return response.ToString(); } /// /// Supply your own JsonConverter to override the JSON serialization style /// for any Type of your choosing. You should only register each converter /// once (during application initialization) /// public static void RegisterJsonConverter(JsonConverter converter) { s_SerializationHelper.RegisterJsonConverter(converter); } private static string GetViewAbsoluteURL(string viewUrl) { // Convert the view URL into something the browser will understand string viewAbsoluteURL; if ((!System.Uri.IsWellFormedUriString(viewUrl, UriKind.Absolute)) && (VirtualPathUtility.IsAppRelative(viewUrl))) viewAbsoluteURL = VirtualPathUtility.ToAbsolute(viewUrl); else viewAbsoluteURL = viewUrl; return viewAbsoluteURL; } #region Parsing the JSON data sent in a request private static T ReadJsonFromRequest(JsonReader reader, string objectPath) { if (objectPath == null) return (T)s_SerializationHelper.Deserialize(reader, typeof(T)); else { // Recursively try to find the requested object reader.Read(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: if (objectPath == (string)reader.Value) // Found it return ReadJsonFromRequest(reader, null); else if (objectPath.StartsWith((string)reader.Value + ".")) // Should be a descendent of this one return ReadJsonFromRequest(reader, objectPath.Substring(((string)reader.Value).Length + 1)); break; default: throw new JsonSerializationException("Didn't find the expected prefix: " + objectPath); } } } throw new JsonSerializationException("Didn't find the expected prefix: " + objectPath); } /// /// Deserializes the JSON string posted to the page as a loosely-typed JavascriptObject /// /// The key into the request data collection public static JavaScriptObject ReadJsonFromRequest(this Controller controller, string htmlName) { return ReadJsonFromRequest(controller, htmlName); } /// /// Deserializes the JSON string posted to the page /// /// The type of .NET object expected /// The key into the request data collection public static T ReadJsonFromRequest(this Controller controller, string htmlName) { return ReadJsonFromRequest(controller, htmlName, null); } /// /// Deserializes the JSON string posted to the page /// /// The type of .NET object expected /// The key into the request data collection /// Rather than deserializing the entire JSON string, you can extract an individual object by specifying the path public static T ReadJsonFromRequest(this Controller controller, string htmlName, string jsonObjectPath) { StringReader sr = new System.IO.StringReader(controller.Request[htmlName]); JsonReader reader = new JsonReader(sr); return ReadJsonFromRequest(reader, jsonObjectPath); } #endregion } }