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
}
}