diff --git a/src/Umbraco.Tests/PluginManagerTests.cs b/src/Umbraco.Tests/PluginManagerTests.cs
index 6fe4525cf0..4bc0485bc9 100644
--- a/src/Umbraco.Tests/PluginManagerTests.cs
+++ b/src/Umbraco.Tests/PluginManagerTests.cs
@@ -11,7 +11,6 @@ using umbraco.MacroEngines.Iron;
using umbraco.businesslogic;
using umbraco.cms.businesslogic;
using umbraco.editorControls;
-using umbraco.presentation.umbracobase;
using umbraco.uicontrols;
using umbraco.cms;
@@ -128,6 +127,13 @@ namespace Umbraco.Tests
Assert.AreEqual(2, types.Count());
}
+ [Test]
+ public void Resolves_LegacyRestExtensions()
+ {
+ var types = PluginManager.Current.ResolveLegacyRestExtensions();
+ Assert.AreEqual(1, types.Count());
+ }
+
[Test]
public void Resolves_XsltExtensions()
{
@@ -141,12 +147,18 @@ namespace Umbraco.Tests
}
- [RestExtension("Blah")]
- public class MyRestExtension
+ [umbraco.presentation.umbracobase.RestExtension("Blah")]
+ public class MyLegacyRestExtension
{
}
+ [Umbraco.Web.BaseRest.RestExtension("Blah")]
+ public class MyRestExtesion
+ {
+
+ }
+
public interface IFindMe
{
diff --git a/src/Umbraco.Web.UI/Web.config b/src/Umbraco.Web.UI/Web.config
index aa7e19c746..29683c3913 100644
--- a/src/Umbraco.Web.UI/Web.config
+++ b/src/Umbraco.Web.UI/Web.config
@@ -33,12 +33,12 @@
-
-
+
+
-
-
+
+
diff --git a/src/Umbraco.Web.UI/web.Template.NILSJO.Debug.config b/src/Umbraco.Web.UI/web.Template.NILSJO.Debug.config
index a54f05ac1e..93d55e4563 100644
--- a/src/Umbraco.Web.UI/web.Template.NILSJO.Debug.config
+++ b/src/Umbraco.Web.UI/web.Template.NILSJO.Debug.config
@@ -19,7 +19,7 @@
+ value="4.10.0"/>
diff --git a/src/Umbraco.Web/BaseRest/BaseRestHandler.cs b/src/Umbraco.Web/BaseRest/BaseRestHandler.cs
new file mode 100644
index 0000000000..d3e6dc6a89
--- /dev/null
+++ b/src/Umbraco.Web/BaseRest/BaseRestHandler.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Web;
+using System.Web.SessionState;
+using System.Reflection;
+using System.Xml;
+using System.IO;
+using System.Linq;
+
+namespace Umbraco.Web.BaseRest
+{
+ internal class BaseRestHandler : IHttpHandler, IRequiresSessionState
+ {
+ static string _baseUrl;
+
+ static BaseRestHandler()
+ {
+ _baseUrl = UriUtility.ToAbsolute(Umbraco.Core.IO.SystemDirectories.Base).ToLower();
+ if (!_baseUrl.EndsWith("/"))
+ _baseUrl += "/";
+ }
+
+ public bool IsReusable
+ {
+ get { return true; }
+ }
+
+ ///
+ /// Returns a value indicating whether a specified Uri should be routed to the BaseRestHandler.
+ ///
+ /// The specified Uri.
+ /// A value indicating whether the specified Uri should be routed to the BaseRestHandler.
+ public static bool IsBaseRestRequest(Uri uri)
+ {
+ return Umbraco.Core.Configuration.UmbracoSettings.EnableBaseRestHandler
+ && uri.AbsolutePath.ToLowerInvariant().StartsWith(_baseUrl);
+ }
+
+ public void ProcessRequest(HttpContext context)
+ {
+ string url = context.Request.RawUrl;
+
+ // sanitize and split the url
+ url = url.Substring(_baseUrl.Length);
+ if (url.ToLower().Contains(".aspx"))
+ url = url.Substring(0, url.IndexOf(".aspx"));
+ if (url.ToLower().Contains("?"))
+ url = url.Substring(0, url.IndexOf("?"));
+ var urlParts = url.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+
+ // by default, return xml content
+ context.Response.ContentType = "text/xml";
+
+ // ensure that we have a valid request ie /base/library/method/[parameter].aspx
+ if (urlParts.Length < 2)
+ {
+ context.Response.Write("Invalid request, missing parts.");
+ context.Response.StatusCode = 400;
+ context.Response.StatusDescription = "Bad Request";
+ context.Response.End();
+ return;
+ }
+
+ string extensionAlias = urlParts[0];
+ string methodName = urlParts[1];
+
+ var method = RestExtensionMethodInfo.GetMethod(extensionAlias, methodName);
+
+ if (!method.Exists)
+ {
+ context.Response.StatusCode = 500;
+ context.Response.StatusDescription = "Internal Server Error";
+ context.Response.Output.Write("Extension or method not found.");
+ }
+ else if (!method.CanBeInvokedByCurrentMember)
+ {
+ context.Response.StatusCode = 500;
+ context.Response.StatusDescription = "Internal Server Error";
+ context.Response.Output.Write("Permission denied.");
+ }
+ else
+ {
+ if (!method.ReturnXml)
+ context.Response.ContentType = "text/html";
+
+ TrySetCulture();
+
+ string result = method.Invoke(urlParts.Skip(2).ToArray());
+ if (result.Length >= 7 && result.Substring(0, 7) == "")
+ {
+ context.Response.StatusCode = 500;
+ context.Response.StatusDescription = "Internal Server Error";
+ }
+ context.Response.Output.Write(result);
+ }
+
+ context.Response.End();
+ }
+
+ #region from baseHttpModule.cs
+
+ // fixme - is this ok?
+
+ private static void TrySetCulture()
+ {
+ string domain = HttpContext.Current.Request.Url.Host; // host only
+ if (TrySetCulture(domain)) return;
+
+ domain = HttpContext.Current.Request.Url.Authority; // host with port
+ if (TrySetCulture(domain)) return;
+ }
+
+ private static bool TrySetCulture(string domain)
+ {
+ var uDomain = global::umbraco.cms.businesslogic.web.Domain.GetDomain(domain);
+ if (uDomain == null) return false;
+ System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(uDomain.Language.CultureAlias);
+ return true;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Umbraco.Web/BaseRest/MemberRest.cs b/src/Umbraco.Web/BaseRest/MemberRest.cs
new file mode 100644
index 0000000000..07f41504c4
--- /dev/null
+++ b/src/Umbraco.Web/BaseRest/MemberRest.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.XPath;
+
+using umbraco.cms.businesslogic;
+using umbraco.cms.businesslogic.member;
+using umbraco.cms.businesslogic.property;
+
+namespace Umbraco.Web.BaseRest
+{
+ public class MemberRest
+ {
+ public static int GetCurrentMemberId()
+ {
+ return Member.CurrentMemberId();
+ }
+
+ public static Member GetCurrentMember()
+ {
+ return Member.GetCurrentMember();
+ }
+
+ public static int Login(string login, string password)
+ {
+ Member m = Member.GetMemberFromLoginNameAndPassword(login, password);
+ var id = GetCurrentMemberId();
+ if (id == 0)
+ {
+ if (m == null)
+ {
+ return 0;
+ }
+ else
+ {
+ Member.AddMemberToCache(m);
+ return m.Id;
+ }
+ }
+ else
+ {
+ return id;
+ }
+ }
+
+ [Obsolete("Use Login(login, password).", false)]
+ public static int login(string loginname, string password)
+ {
+ return Login(loginname, password);
+ }
+
+ public static int Logout()
+ {
+ var currentId = GetCurrentMemberId();
+ if (currentId > 0)
+ {
+ Member.RemoveMemberFromCache(currentId);
+ Member.ClearMemberFromClient(currentId);
+ return currentId;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ [Obsolete("Use Logout().", false)]
+ public static int logout(int NodeId)
+ {
+ return Logout();
+ }
+
+ [Obsolete("Use Logout().", false)]
+ public static int logout()
+ {
+ return Logout();
+ }
+
+ public static XPathNodeIterator Data()
+ {
+ var m = GetCurrentMember();
+ if (m != null)
+ {
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(m.ToXml(doc, false).OuterXml);
+ XPathNavigator nav = doc.CreateNavigator();
+ return nav.Select("/node");
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ [Obsolete("Use Data().", false)]
+ public static XPathNodeIterator data()
+ {
+ return Data();
+ }
+
+ [Obsolete("Use GetCurrentMemberId().", false)]
+ public static int id()
+ {
+ return GetCurrentMemberId();
+ }
+
+ public static string SetProperty(string alias, object value)
+ {
+ string ret = "False";
+
+ try
+ {
+ var m = GetCurrentMember();
+
+ if (m != null)
+ {
+ var prop = m.getProperty(alias);
+
+ if (m.ContentType != null && MemberType.GetByAlias(m.ContentType.Alias).MemberCanEdit(prop.PropertyType))
+ {
+
+ if (prop.PropertyType.ValidationRegExp.Trim() != "")
+ {
+ Regex regex = new Regex(m.getProperty(alias).PropertyType.ValidationRegExp);
+
+ if (regex.IsMatch(value.ToString()))
+ {
+ prop.Value = value;
+ ret = "True";
+ m.XmlGenerate(new XmlDocument());
+ }
+ }
+ else
+ {
+ prop.Value = value;
+ ret = "True";
+ m.XmlGenerate(new XmlDocument());
+ }
+
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ ret = e.Message;
+ }
+
+ return ret;
+ }
+
+ [Obsolete("Use SetProperty(alias, value).", false)]
+ public static string setProperty(string alias, object value)
+ {
+ return SetProperty(alias, value);
+ }
+ }
+}
diff --git a/src/Umbraco.Web/BaseRest/RestExtensionAttribute.cs b/src/Umbraco.Web/BaseRest/RestExtensionAttribute.cs
new file mode 100644
index 0000000000..fa840388bb
--- /dev/null
+++ b/src/Umbraco.Web/BaseRest/RestExtensionAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Umbraco.Web.BaseRest
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class RestExtensionAttribute : Attribute
+ {
+ public string Alias { get; private set; }
+
+ public RestExtensionAttribute(string alias)
+ {
+ this.Alias = alias;
+ }
+ }
+}
diff --git a/src/Umbraco.Web/BaseRest/RestExtensionMethodAttribute.cs b/src/Umbraco.Web/BaseRest/RestExtensionMethodAttribute.cs
new file mode 100644
index 0000000000..7d21c08d58
--- /dev/null
+++ b/src/Umbraco.Web/BaseRest/RestExtensionMethodAttribute.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Umbraco.Web.BaseRest
+{
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
+ public class RestExtensionMethodAttribute : Attribute
+ {
+ public bool AllowAll { get; set; }
+ public string AllowGroup { get; set; }
+ public string AllowType { get; set; }
+ public string AllowMember { get; set; }
+ public bool ReturnXml { get; set; }
+
+ public RestExtensionMethodAttribute()
+ {
+ this.AllowAll = true;
+ this.ReturnXml = true;
+ }
+ }
+}
diff --git a/src/Umbraco.Web/BaseRest/RestExtensionMethodInfo.cs b/src/Umbraco.Web/BaseRest/RestExtensionMethodInfo.cs
new file mode 100644
index 0000000000..934d0e5732
--- /dev/null
+++ b/src/Umbraco.Web/BaseRest/RestExtensionMethodInfo.cs
@@ -0,0 +1,344 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Reflection;
+using System.Xml;
+using System.IO;
+
+using Umbraco.Core;
+using Umbraco.Core.IO;
+using umbraco.cms.businesslogic.member;
+
+namespace Umbraco.Web.BaseRest
+{
+ class RestExtensionMethodInfo
+ {
+ #region Utilities
+
+ static char[] Split = new char[] { ',' };
+
+ static string[] SplitString(string s)
+ {
+ if (string.IsNullOrWhiteSpace(s))
+ return new string[] { };
+ else
+ return s.ToLower().Split(Split, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ static string GetAttribute(XmlNode node, string name)
+ {
+ var attribute = node.Attributes[name];
+ return attribute == null ? null : attribute.Value;
+ }
+
+ #endregion
+
+ private RestExtensionMethodInfo()
+ {
+ this.Exists = false;
+ }
+
+ private RestExtensionMethodInfo(bool allowAll, string allowGroup, string allowType, string allowMember, bool returnXml, MethodInfo method)
+ {
+ this.Exists = true;
+ _allowAll = allowAll;
+ _allowGroups = SplitString(allowGroup);
+ _allowTypes = SplitString(allowType);
+ _allowMembers = SplitString(allowMember);
+ this.ReturnXml = returnXml;
+ _method = method;
+ }
+
+ static RestExtensionMethodInfo MissingMethod = new RestExtensionMethodInfo();
+ static Dictionary _cache = new Dictionary();
+
+ bool _allowAll;
+ string[] _allowGroups;
+ string[] _allowTypes;
+ string[] _allowMembers;
+ MethodInfo _method;
+
+ public bool Exists { get; private set; }
+ public bool ReturnXml { get; private set; }
+
+ #region Discovery
+
+ public static RestExtensionMethodInfo GetMethod(string extensionAlias, string methodName)
+ {
+ return GetFromConfiguration(extensionAlias, methodName)
+ ?? GetFromAttribute(extensionAlias, methodName)
+ ?? GetFromLegacyAttribute(extensionAlias, methodName)
+ ?? MissingMethod;
+ }
+
+ static RestExtensionMethodInfo GetFromConfiguration(string extensionAlias, string methodName)
+ {
+ const string ExtensionXPath = "/RestExtensions/ext [@alias='{0}']";
+ const string MethodXPath = "./permission [@method='{0}']";
+
+ // fixme
+ // because we reload the config file each time we can't really have a cache here
+ // or we'd need to set a watcher on the config file?
+
+ var doc = new XmlDocument();
+ doc.Load(IOHelper.MapPath(SystemFiles.RestextensionsConfig));
+
+ var eNode = doc.SelectSingleNode(string.Format(ExtensionXPath, extensionAlias));
+
+ if (eNode == null)
+ return null; // does not exist
+
+ var mNode = eNode.SelectSingleNode(string.Format(MethodXPath, methodName));
+
+ if (mNode == null)
+ return null; // does not exist
+
+ string assemblyName = eNode.Attributes["assembly"].Value;
+ string assemblyPath = IOHelper.MapPath(string.Format("{0}/{1}.dll", SystemDirectories.Bin, assemblyName.TrimStart('/')));
+ Assembly assembly = Assembly.LoadFrom(assemblyPath);
+
+ string typeName = eNode.Attributes["type"].Value;
+ Type type = assembly.GetType(typeName);
+
+ var method = type.GetMethod(methodName);
+
+ if (method == null)
+ return null; // does not exist
+
+ var allowAll = GetAttribute(mNode, "allowAll");
+ var returnXml = GetAttribute(mNode, "returnXml");
+
+ var info = new RestExtensionMethodInfo(allowAll != null && allowAll.ToLower() == "true",
+ GetAttribute(mNode, "allowGroup"), GetAttribute(mNode, "allowType"), GetAttribute(mNode, "allowMember"),
+ returnXml == null || returnXml.ToLower() != "false",
+ method);
+
+ return info;
+ }
+
+ static RestExtensionMethodInfo GetFromLegacyAttribute(string extensionAlias, string methodName)
+ {
+ // here we can cache because any change would trigger an app restart
+
+ string cacheKey = extensionAlias + "." + methodName;
+ lock (_cache)
+ {
+ if (_cache.ContainsKey(cacheKey))
+ return _cache[cacheKey];
+ }
+
+ var extensions = PluginManager.Current.ResolveLegacyRestExtensions();
+ var extension = extensions
+ .SingleOrDefault(type => type.GetCustomAttribute(false).GetAlias() == extensionAlias);
+
+ RestExtensionMethodInfo info = null;
+
+ if (extension != null)
+ {
+ var method = extension.GetMethod(methodName);
+ if (method != null)
+ {
+ var attribute = method.GetCustomAttributes(typeof(global::umbraco.presentation.umbracobase.RestExtensionMethod), false).Cast().SingleOrDefault();
+ if (attribute != null)
+ {
+ info = new RestExtensionMethodInfo(attribute.GetAllowAll(),
+ attribute.GetAllowGroup(), attribute.GetAllowType(), attribute.GetAllowMember(),
+ attribute.returnXml,
+ method);
+ }
+ }
+ }
+
+ lock (_cache)
+ {
+ _cache[cacheKey] = info;
+ }
+
+ return info;
+ }
+
+ static RestExtensionMethodInfo GetFromAttribute(string extensionAlias, string methodName)
+ {
+ // here we can cache because any change would trigger an app restart
+
+ string cacheKey = extensionAlias + "." + methodName;
+ lock (_cache)
+ {
+ if (_cache.ContainsKey(cacheKey))
+ return _cache[cacheKey];
+ }
+
+ var extensions = PluginManager.Current.ResolveRestExtensions();
+ var extension = extensions
+ .SingleOrDefault(type => type.GetCustomAttribute(false).Alias == extensionAlias);
+
+ RestExtensionMethodInfo info = null;
+
+ if (extension != null)
+ {
+ var method = extension.GetMethod(methodName);
+ if (method != null)
+ {
+ var attribute = method.GetCustomAttributes(typeof(RestExtensionMethodAttribute), false).Cast().SingleOrDefault();
+ if (attribute != null)
+ {
+ info = new RestExtensionMethodInfo(attribute.AllowAll,
+ attribute.AllowGroup, attribute.AllowType, attribute.AllowMember,
+ attribute.ReturnXml,
+ method);
+ }
+ }
+ }
+
+ lock (_cache)
+ {
+ _cache[cacheKey] = info;
+ }
+
+ return info;
+ }
+
+ #endregion
+
+ #region Invoke
+
+ public bool CanBeInvokedByCurrentMember
+ {
+ get
+ {
+ if (_allowAll)
+ return true;
+
+ var member = Member.GetCurrentMember();
+
+ if (member == null)
+ return false;
+
+ bool allowed = false;
+
+ if (_allowGroups.Length > 0)
+ {
+ // fixme - are these equivalent?
+ //var groups = member.Groups.Values.Cast().Select(group => group.Text);
+ var groups = System.Web.Security.Roles.GetRolesForUser(member.LoginName);
+ allowed = groups.Select(s => s.ToLower()).Intersect(_allowGroups).Any();
+ }
+
+ if (!allowed && _allowTypes.Length > 0)
+ {
+ allowed = _allowTypes.Contains(member.ContentType.Alias);
+ }
+
+ if (!allowed && _allowMembers.Length > 0)
+ {
+ allowed = _allowMembers.Contains(member.Id.ToString());
+ }
+
+ return allowed;
+ }
+ }
+
+ public string Invoke(string[] parameters)
+ {
+ try
+ {
+ if (!_method.IsPublic || !_method.IsStatic)
+ {
+ // ensure that method is static public
+ return "Method has to be public and static";
+ }
+ else
+ {
+ // ensure we have the right number of parameters
+ if (_method.GetParameters().Length != parameters.Length)
+ {
+ return "Not Enough parameters in url";
+ }
+ else
+ {
+ // invoke
+
+ // fixme - what is the point?
+ //Create an instance of the type we need to invoke the method from.
+ //**Object obj = Activator.CreateInstance(myExtension.type);
+
+ object response;
+
+ if (_method.GetParameters().Length == 0)
+ {
+ //response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, null, System.Globalization.CultureInfo.CurrentCulture);
+ response = _method.Invoke(null /*obj*/, null); // invoke with null as parameters as there are none
+ }
+
+ else
+ {
+ object[] methodParams = new object[parameters.Length];
+
+ int i = 0;
+
+ foreach (ParameterInfo pInfo in _method.GetParameters())
+ {
+ Type myType = Type.GetType(pInfo.ParameterType.ToString());
+ methodParams[(i)] = Convert.ChangeType(parameters[i], myType);
+ i++;
+ }
+
+ //Invoke with methodParams
+ //response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, methodParams, System.Globalization.CultureInfo.CurrentCulture);
+ response = _method.Invoke(/*obj*/null, methodParams);
+ }
+
+ /*TODO - SOMETHING ALITTLE BETTER THEN ONLY CHECK FOR XPATHNODEITERATOR OR ELSE do ToString() */
+ if (response != null)
+ {
+ switch (_method.ReturnType.ToString())
+ {
+ case "System.Xml.XPath.XPathNodeIterator":
+ return ((System.Xml.XPath.XPathNodeIterator)response).Current.OuterXml;
+ case "System.Xml.Linq.XDocument":
+ return response.ToString();
+ case "System.Xml.XmlDocument":
+ XmlDocument xmlDoc = (XmlDocument)response;
+ StringWriter sw = new StringWriter();
+ XmlTextWriter xw = new XmlTextWriter(sw);
+ xmlDoc.WriteTo(xw);
+ return sw.ToString();
+ default:
+ string strResponse = ((string)response.ToString());
+
+ if (this.ReturnXml)
+ {
+ // do a quick "is this html?" check... if it is add CDATA...
+ if (strResponse.Contains("<") || strResponse.Contains(">"))
+ strResponse = "";
+ return "" + strResponse + "";
+ }
+ else
+ {
+ //HttpContext.Current.Response.ContentType = "text/html";
+ return strResponse;
+ }
+ }
+ }
+ else
+ {
+ if (this.ReturnXml)
+ return "Null value returned";
+ else
+ return string.Empty;
+ }
+ }
+ }
+ }
+
+ catch (Exception ex)
+ {
+ //Overall exception handling...
+ return "";
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Umbraco.Web/BaseRestHandler.cs b/src/Umbraco.Web/BaseRestHandler.cs
deleted file mode 100644
index 9f2b3323cd..0000000000
--- a/src/Umbraco.Web/BaseRestHandler.cs
+++ /dev/null
@@ -1,218 +0,0 @@
-using System;
-using System.Web;
-using System.Web.SessionState;
-using System.Reflection;
-using System.Xml;
-using System.IO;
-
-namespace Umbraco.Web
-{
- internal class BaseRestHandler : IHttpHandler, IRequiresSessionState
- {
- const int ParametersOffset = 2;
- static string _baseUrl;
-
- static BaseRestHandler()
- {
- _baseUrl = UriUtility.ToAbsolute(Umbraco.Core.IO.SystemDirectories.Base).ToLower();
- if (!_baseUrl.EndsWith("/"))
- _baseUrl += "/";
- }
-
- public bool IsReusable
- {
- get { return true; }
- }
-
- ///
- /// Returns a value indicating whether a specified Uri should be routed to the BaseRestHandler.
- ///
- /// The specified Uri.
- /// A value indicating whether the specified Uri should be routed to the BaseRestHandler.
- public static bool IsBaseRestRequest(Uri uri)
- {
- return Umbraco.Core.Configuration.UmbracoSettings.EnableBaseRestHandler
- && uri.AbsolutePath.ToLowerInvariant().StartsWith(_baseUrl);
- }
-
- public void ProcessRequest(HttpContext context)
- {
- string url = context.Request.RawUrl;
-
- // sanitize and split the url
- url = url.Substring(_baseUrl.Length);
- if (url.ToLower().Contains(".aspx"))
- url = url.Substring(0, url.IndexOf(".aspx"));
- if (url.ToLower().Contains("?"))
- url = url.Substring(0, url.IndexOf("?"));
- var urlParts = url.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
-
- // always return xml content
- context.Response.ContentType = "text/xml";
-
- // ensure that we have a valid request ie /base/library/method/[parameter].aspx
- if (urlParts.Length < ParametersOffset)
- {
- context.Response.Write("Invalid request, missing parts.");
- context.Response.StatusCode = 400;
- context.Response.StatusDescription = "Bad Request";
- context.Response.End();
- return;
- }
-
- // fixme - what follows comes straight from baseHttpModule.cs
-
- string extensionAlias = urlParts[0];
- string methodName = urlParts[1];
-
- var myExtension = new global::umbraco.presentation.umbracobase.restExtension(extensionAlias, methodName);
-
- if (myExtension.isAllowed)
- {
- TrySetCulture();
-
- string response = invokeMethod(myExtension, urlParts);
- if (response.Length >= 7 && response.Substring(0, 7) == "")
- {
- context.Response.StatusCode = 500;
- context.Response.StatusDescription = "Internal Server Error";
- }
- context.Response.Output.Write(response);
- }
- else
- {
- context.Response.StatusCode = 500;
- context.Response.StatusDescription = "Internal Server Error";
- context.Response.Output.Write("Extension not found or permission denied.");
- }
-
- context.Response.End();
- }
-
- #region from baseHttpModule.cs
-
- // fixme - these methods have *not* been cleaned up, just partially fixed...
-
- string invokeMethod(global::umbraco.presentation.umbracobase.restExtension myExtension, string[] urlParts)
- {
- try
- {
- //So method is either not found or not valid... this should probably be moved...
- if (!myExtension.method.IsPublic || !myExtension.method.IsStatic)
- return "Method has to be public and static";
- else //And if it is lets continue trying to invoke it...
- {
- //lets check if we have parameters enough in the url..
- if (myExtension.method.GetParameters().Length > (urlParts.Length - ParametersOffset)) //Too few
- return "Not Enough parameters in url";
- else
- {
-
- //We have enough parameters... lets invoke..
- //Create an instance of the type we need to invoke the method from.
- //**Object obj = Activator.CreateInstance(myExtension.type);
- Object response;
-
- //umbracoBase.baseBinder bBinder = new baseBinder();
-
- if (myExtension.method.GetParameters().Length == 0)
- {
- //response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, null, System.Globalization.CultureInfo.CurrentCulture);
- response = myExtension.method.Invoke(null /*obj*/, null); //Invoke with null as parameters as there are none
- }
-
- else
- {
- //We only need the parts of the url above the number 4 so we'll
- //recast those to objects and add them to the object[]
-
- //Getting the right lenght.. 4 is the magic number dum di dum..
- object[] methodParams = new object[urlParts.Length - ParametersOffset];
-
- int i = 0;
-
- foreach (ParameterInfo pInfo in myExtension.method.GetParameters())
- {
- Type myType = Type.GetType(pInfo.ParameterType.ToString());
- methodParams[(i)] = Convert.ChangeType(urlParts[i + ParametersOffset], myType);
- i++;
- }
-
- //Invoke with methodParams
- //response = myMethod.method.Invoke(obj, BindingFlags.Public | BindingFlags.Instance, bBinder, methodParams, System.Globalization.CultureInfo.CurrentCulture);
- response = myExtension.method.Invoke(/*obj*/null, methodParams);
- }
-
- /*TODO - SOMETHING ALITTLE BETTER THEN ONLY CHECK FOR XPATHNODEITERATOR OR ELSE do ToString() */
- if (response != null)
- {
- switch (myExtension.method.ReturnType.ToString())
- {
- case "System.Xml.XPath.XPathNodeIterator":
- return ((System.Xml.XPath.XPathNodeIterator)response).Current.OuterXml;
- case "System.Xml.Linq.XDocument":
- return response.ToString();
- case "System.Xml.XmlDocument":
- XmlDocument xmlDoc = (XmlDocument)response;
- StringWriter sw = new StringWriter();
- XmlTextWriter xw = new XmlTextWriter(sw);
- xmlDoc.WriteTo(xw);
- return sw.ToString();
- default:
- string strResponse = ((string)response.ToString());
-
- if (myExtension.returnXML)
- {
- //do a quick "is this html?" check... if it is add CDATA...
- if (strResponse.Contains("<") || strResponse.Contains(">"))
- strResponse = "";
- return "" + strResponse + "";
- }
- else
- {
- HttpContext.Current.Response.ContentType = "text/html";
- return strResponse;
- }
- }
- }
- else
- {
- if (myExtension.returnXML)
- return "Null value returned";
- else
- return string.Empty;
- }
-
-
-
- }
- }
- }
-
- catch (Exception ex)
- {
- //Overall exception handling...
- return "";
- }
- }
-
- private static void TrySetCulture()
- {
- string domain = HttpContext.Current.Request.Url.Host; //Host only
- if (TrySetCulture(domain)) return;
-
- domain = HttpContext.Current.Request.Url.Authority; //Host with port
- if (TrySetCulture(domain)) return;
- }
-
- private static bool TrySetCulture(string domain)
- {
- var uDomain = global::umbraco.cms.businesslogic.web.Domain.GetDomain(domain);
- if (uDomain == null) return false;
- System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(uDomain.Language.CultureAlias);
- return true;
- }
-
- #endregion
- }
-}
diff --git a/src/Umbraco.Web/PluginManagerExtensions.cs b/src/Umbraco.Web/PluginManagerExtensions.cs
index 13db38e9d2..5ff0e9f81d 100644
--- a/src/Umbraco.Web/PluginManagerExtensions.cs
+++ b/src/Umbraco.Web/PluginManagerExtensions.cs
@@ -6,8 +6,6 @@ using Umbraco.Core;
using Umbraco.Web.Routing;
using umbraco;
using umbraco.interfaces;
-using umbraco.presentation.umbracobase;
-
namespace Umbraco.Web
{
@@ -27,13 +25,23 @@ namespace Umbraco.Web
}
///
- /// Returns all classes attributed with RestExtension attribute
+ /// Returns all classes attributed with legacy RestExtension attribute
+ ///
+ ///
+ ///
+ internal static IEnumerable ResolveLegacyRestExtensions(this PluginManager resolver)
+ {
+ return resolver.ResolveAttributedTypes();
+ }
+
+ ///
+ /// Returns all classes attributed with RestExtensionAttribute attribute
///
///
///
internal static IEnumerable ResolveRestExtensions(this PluginManager resolver)
{
- return resolver.ResolveAttributedTypes();
+ return resolver.ResolveAttributedTypes();
}
///
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 9f9411fed2..2dd5bdb20d 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -240,7 +240,11 @@
Properties\SolutionInfo.cs
-
+
+
+
+
+
diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs
index 4798931c16..d5b400e3bd 100644
--- a/src/Umbraco.Web/UmbracoModule.cs
+++ b/src/Umbraco.Web/UmbracoModule.cs
@@ -67,9 +67,9 @@ namespace Umbraco.Web
umbracoContext.RoutingContext = routingContext;
// remap to handler if it is a base rest request
- if (BaseRestHandler.IsBaseRestRequest(umbracoContext.RequestUrl))
+ if (BaseRest.BaseRestHandler.IsBaseRestRequest(umbracoContext.RequestUrl))
{
- httpContext.RemapHandler(new BaseRestHandler());
+ httpContext.RemapHandler(new BaseRest.BaseRestHandler());
}
else
diff --git a/src/Umbraco.Web/WebServices/FolderBrowserService.cs b/src/Umbraco.Web/WebServices/FolderBrowserService.cs
index 82684d7b1e..02132356f0 100644
--- a/src/Umbraco.Web/WebServices/FolderBrowserService.cs
+++ b/src/Umbraco.Web/WebServices/FolderBrowserService.cs
@@ -11,14 +11,14 @@ using umbraco.BusinessLogic;
using umbraco.IO;
using umbraco.cms.businesslogic.Tags;
using umbraco.cms.businesslogic.media;
-using umbraco.presentation.umbracobase;
+using Umbraco.Web.BaseRest;
namespace Umbraco.Web.WebServices
{
[RestExtension("FolderBrowserService")]
public class FolderBrowserService
{
- [RestExtensionMethod(returnXml = false)]
+ [RestExtensionMethod(ReturnXml = false)]
public static string GetChildren(int parentId)
{
var parentMedia = new global::umbraco.cms.businesslogic.media.Media(parentId);
@@ -64,7 +64,7 @@ namespace Umbraco.Web.WebServices
return new JavaScriptSerializer().Serialize(data);
}
- [RestExtensionMethod(returnXml = false)]
+ [RestExtensionMethod(ReturnXml = false)]
public static string Delete(string nodeIds)
{
var nodeIdParts = nodeIds.Split(',');
diff --git a/src/Umbraco.Web/umbraco.presentation/umbracobase/attributes/RestExtension.cs b/src/Umbraco.Web/umbraco.presentation/umbracobase/attributes/RestExtension.cs
index f9839fb588..202fa76a40 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbracobase/attributes/RestExtension.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbracobase/attributes/RestExtension.cs
@@ -5,6 +5,7 @@ using System.Web;
namespace umbraco.presentation.umbracobase
{
+ [Obsolete("Use Umbraco.Web.BaseRest.RestExtensionAttribute")]
[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = false)]
public class RestExtension : System.Attribute
{
diff --git a/src/Umbraco.Web/umbraco.presentation/umbracobase/attributes/RestExtensionMethod.cs b/src/Umbraco.Web/umbraco.presentation/umbracobase/attributes/RestExtensionMethod.cs
index 4836fc7a78..f11c5d644b 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbracobase/attributes/RestExtensionMethod.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbracobase/attributes/RestExtensionMethod.cs
@@ -5,6 +5,7 @@ using System.Web;
namespace umbraco.presentation.umbracobase
{
+ [Obsolete("Use Umbraco.Web.BaseRest.RestExtensionMethodAttribute")]
[System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = false)]
public class RestExtensionMethod : System.Attribute
{
diff --git a/src/Umbraco.Web/umbraco.presentation/umbracobase/restExtension.cs b/src/Umbraco.Web/umbraco.presentation/umbracobase/restExtension.cs
index d7ee34bebc..dbeab6cf53 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbracobase/restExtension.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbracobase/restExtension.cs
@@ -10,6 +10,7 @@ using umbraco.IO;
namespace umbraco.presentation.umbracobase
{
+ [Obsolete]
public class restExtension
{
private Type _type;