diff --git a/IronRubyMvc.Tests/Controllers/AfterActionFilter.cs b/IronRubyMvc.Tests/Controllers/AfterActionFilter.cs deleted file mode 100644 index 8458cfb..0000000 --- a/IronRubyMvc.Tests/Controllers/AfterActionFilter.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Web.Mvc; - -namespace IronRubyMvcLibrary.Tests.Controllers -{ - public class AfterActionFilter : DelegateActionFilter - { - public AfterActionFilter(Action onActionExecuted) - : base(null, onActionExecuted) - { - } - } -} \ No newline at end of file diff --git a/IronRubyMvc.Tests/Controllers/AroundActionFilter.cs b/IronRubyMvc.Tests/Controllers/AroundActionFilter.cs deleted file mode 100644 index 9b3106a..0000000 --- a/IronRubyMvc.Tests/Controllers/AroundActionFilter.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace IronRubyMvcLibrary.Tests.Controllers -{ - public class AroundActionFilter - { - - } -} \ No newline at end of file diff --git a/IronRubyMvc.Tests/Controllers/BeforeActionFilter.cs b/IronRubyMvc.Tests/Controllers/BeforeActionFilter.cs deleted file mode 100644 index d515cda..0000000 --- a/IronRubyMvc.Tests/Controllers/BeforeActionFilter.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Web.Mvc; - -namespace IronRubyMvcLibrary.Tests.Controllers -{ - public class BeforeActionFilter : DelegateActionFilter - { - public BeforeActionFilter(Action onActionExecuting) : base(onActionExecuting, null) - { - } - } - - -} \ No newline at end of file diff --git a/IronRubyMvc.Tests/Controllers/DelegateActionFilter.cs b/IronRubyMvc.Tests/Controllers/DelegateActionFilter.cs index 50419b6..e37b9d3 100644 --- a/IronRubyMvc.Tests/Controllers/DelegateActionFilter.cs +++ b/IronRubyMvc.Tests/Controllers/DelegateActionFilter.cs @@ -8,28 +8,39 @@ namespace IronRubyMvcLibrary.Tests.Controllers { - public abstract class DelegateActionFilter : IActionFilter - { - private readonly Action _onActionExecuted; - private readonly Action _onActionExecuting; + - protected DelegateActionFilter(Action onActionExecuting, - Action onActionExecuted) - { - _onActionExecuting = onActionExecuting; - _onActionExecuted = onActionExecuted; - } + public abstract class DelegateActionFilter : IActionFilter, IResultFilter + { + public Action BeforeAction { get; set; } + public Action AfterAction { get; set; } + public Action BeforeResult { get; set; } + public Action AfterResult { get; set; } #region IActionFilter Members public virtual void OnActionExecuting(ActionExecutingContext filterContext) { - if(_onActionExecuting.IsNotNull()) _onActionExecuting(filterContext); + if(BeforeAction.IsNotNull()) BeforeAction(filterContext); } public virtual void OnActionExecuted(ActionExecutedContext filterContext) { - if(_onActionExecuted.IsNotNull()) _onActionExecuted(filterContext); + if(AfterAction.IsNotNull()) AfterAction(filterContext); + } + + #endregion + + #region Implementation of IResultFilter + + public virtual void OnResultExecuting(ResultExecutingContext filterContext) + { + if (BeforeResult.IsNotNull()) BeforeResult(filterContext); + } + + public virtual void OnResultExecuted(ResultExecutedContext filterContext) + { + if (AfterResult.IsNotNull()) AfterResult(filterContext); } #endregion diff --git a/IronRubyMvc.Tests/Controllers/DelegateResultFilter.cs b/IronRubyMvc.Tests/Controllers/DelegateResultFilter.cs deleted file mode 100644 index a553273..0000000 --- a/IronRubyMvc.Tests/Controllers/DelegateResultFilter.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace IronRubyMvcLibrary.Tests.Controllers -{ - public class DelegateResultFilter - { - - } -} \ No newline at end of file diff --git a/IronRubyMvc.Tests/Controllers/ResultFilter.cs b/IronRubyMvc.Tests/Controllers/ResultFilter.cs deleted file mode 100644 index d501a8a..0000000 --- a/IronRubyMvc.Tests/Controllers/ResultFilter.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace IronRubyMvcLibrary.Tests.Controllers -{ - public class ResultFilter - { - - } -} \ No newline at end of file diff --git a/IronRubyMvc.Tests/IronRubyMvcLibrary.Tests.csproj b/IronRubyMvc.Tests/IronRubyMvcLibrary.Tests.csproj index 8b1db8b..f8fc902 100644 --- a/IronRubyMvc.Tests/IronRubyMvcLibrary.Tests.csproj +++ b/IronRubyMvc.Tests/IronRubyMvcLibrary.Tests.csproj @@ -95,6 +95,7 @@ + diff --git a/IronRubyMvc/Controllers/HashToActionFilterConverter.cs b/IronRubyMvc/Controllers/HashToActionFilterConverter.cs new file mode 100644 index 0000000..44cd335 --- /dev/null +++ b/IronRubyMvc/Controllers/HashToActionFilterConverter.cs @@ -0,0 +1,73 @@ +using System.Collections; +using System.Collections.Generic; +using System.IO; +using IronRuby.Builtins; +using IronRubyMvcLibrary.Core; +using IronRubyMvcLibrary.Extensions; +using Microsoft.Scripting; + +namespace IronRubyMvcLibrary.Controllers +{ + public interface IConverter + { + TTarget Convert(); + } + public class HashToActionFilterConverter : IConverter + { + private readonly Hash _filterDescription; + + private static readonly IEnumerable _actionFilterDenominators = new[] + { + SymbolTable.StringToId("before"), + SymbolTable.StringToId("after"), + SymbolTable.StringToId("around"), + SymbolTable.StringToId("before_result"), + SymbolTable.StringToId("after_result") + }; + + private static readonly IDictionary _actionWhen = new Dictionary + { + {When.BeforeAction, SymbolTable.StringToId("before")}, + {When.AfterAction, SymbolTable.StringToId("after")}, + {When.BeforeResult, SymbolTable.StringToId("before_result")}, + {When.AfterResult, SymbolTable.StringToId("after_result")}, + + }; + + private static readonly SymbolId whenKey = SymbolTable.StringToId("when"); + + public HashToActionFilterConverter(Hash filterDescription) + { + _filterDescription = filterDescription; + } + + #region Implementation of IConverter + + public RubyActionFilter Convert() + { + if (!IsActionFilter(_filterDescription)) + throw new InvalidDataException("The filter description is invalid."); + + return new RubyActionFilter + { + BeforeAction = FindProc(_filterDescription, _actionWhen[When.BeforeAction]), + AfterAction = FindProc(_filterDescription, _actionWhen[When.AfterAction]), + BeforeResult = FindProc(_filterDescription, _actionWhen[When.BeforeResult]), + AfterResult = FindProc(_filterDescription, _actionWhen[When.AfterResult]) + }; + } + + #endregion + + private static bool IsActionFilter(IDictionary hash) + { + var key = (SymbolId)hash[whenKey]; + return _actionFilterDenominators.Contains(key); + } + + private static Proc FindProc(IDictionary hash, SymbolId key) + { + return hash.ContainsKey(key) ? (Proc)hash[key] : null; + } + } +} \ No newline at end of file diff --git a/IronRubyMvc/Controllers/RubyActionFilter.cs b/IronRubyMvc/Controllers/RubyActionFilter.cs new file mode 100644 index 0000000..e4b14c5 --- /dev/null +++ b/IronRubyMvc/Controllers/RubyActionFilter.cs @@ -0,0 +1,89 @@ +#region Usings + +using System.Collections.Generic; +using System.Web.Mvc; +using IronRuby.Builtins; +using IronRubyMvcLibrary.Core; +using IronRubyMvcLibrary.Extensions; + +#endregion + +namespace IronRubyMvcLibrary.Controllers +{ + /// + /// Implements and + /// This class hooks the ruby defined filters with + /// + public class RubyActionFilter : IActionFilter, IResultFilter + { + public IEnumerable OnlyForActions { get; set; } + public IEnumerable ExceptForActions { get; set; } + public Proc BeforeAction { get; set; } + public Proc AfterAction { get; set; } + public Proc BeforeResult { get; set; } + public Proc AfterResult { get; set; } + public When FilterType { get; set; } + + #region Implementation of IActionFilter + + /// + /// Called before the action executes + /// + /// The filter context. + public void OnActionExecuting(ActionExecutingContext filterContext) + { + if (BeforeAction.IsNotNull() && CanExecute(filterContext)) + BeforeAction.Call(filterContext); + } + + /// + /// Called after an action executed + /// + /// The filter context. + public void OnActionExecuted(ActionExecutedContext filterContext) + { + if ( AfterAction.IsNotNull() && CanExecute(filterContext)) + AfterAction.Call(filterContext); + } + + #endregion + + #region Implementation of IResultFilter + + public void OnResultExecuting(ResultExecutingContext filterContext) + { + if (BeforeResult.IsNotNull()) + BeforeResult.Call(filterContext); + } + + public void OnResultExecuted(ResultExecutedContext filterContext) + { + if (AfterResult.IsNotNull()) + AfterResult.Call(filterContext); + } + + #endregion + + #region Implementation of IRubyControllerFilter + + private bool CanExecute(ActionExecutingContext context) + { + var actionName = context.ActionDescriptor.ActionName; + return CanExecute(actionName); + } + + private bool CanExecute(ActionExecutedContext context) + { + var actionName = context.ActionDescriptor.ActionName; + return CanExecute(actionName); + } + + private bool CanExecute(string actionName) + { + return OnlyForActions.IsEmpty() || OnlyForActions.Contains(actionName) + || ExceptForActions.IsEmpty() || ExceptForActions.DoesNotContain(actionName); + } + + #endregion + } +} \ No newline at end of file diff --git a/IronRubyMvc/Controllers/RubyController.cs b/IronRubyMvc/Controllers/RubyController.cs index b52ba5b..4224c96 100644 --- a/IronRubyMvc/Controllers/RubyController.cs +++ b/IronRubyMvc/Controllers/RubyController.cs @@ -31,10 +31,6 @@ public class RubyController : Controller public string ControllerName { get; internal set; } public RubyClass RubyType { get; private set; } -// public static Hash ActionFilters { get; set; } -// -// public static Hash ActionResult { get; set; } - public string ControllerClassName { get { return Constants.CONTROLLERCLASS_FORMAT.FormattedWith(ControllerName); } diff --git a/IronRubyMvc/Controllers/RubyControllerActionInvoker.cs b/IronRubyMvc/Controllers/RubyControllerActionInvoker.cs index 20c04b9..0978fc8 100644 --- a/IronRubyMvc/Controllers/RubyControllerActionInvoker.cs +++ b/IronRubyMvc/Controllers/RubyControllerActionInvoker.cs @@ -1,6 +1,12 @@ #region Usings +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading; +using System.Web; using System.Web.Mvc; +using IronRuby.Builtins; using IronRubyMvcLibrary.Core; #endregion @@ -30,6 +36,105 @@ protected override ControllerDescriptor GetControllerDescriptor(ControllerContex { return controllerDescriptor.FindAction(controllerContext, actionName); } - + + protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) + { + var rubyType = ((RubyController) controllerContext.Controller).RubyType; + var actionFilters = (Hash) RubyEngine.CallMethod(rubyType, "action_filters"); + var filters = new RubyFilterInfo(actionFilters); + + return filters; + } + + private static void AddControllerToFilterList(ControllerBase controller, IList filterList) + where TFilter : class + { + var controllerAsFilter = controller as TFilter; + if (controllerAsFilter != null) + { + filterList.Insert(0, controllerAsFilter); + } + } + + public override bool InvokeAction(ControllerContext controllerContext, string actionName) + { + if (controllerContext == null) + { + throw new ArgumentNullException("controllerContext"); + } + if (String.IsNullOrEmpty(actionName)) + { + throw new ArgumentException("actionName"); + } + + var controllerDescriptor = GetControllerDescriptor(controllerContext); + var actionDescriptor = FindAction(controllerContext, controllerDescriptor, actionName); + if (actionDescriptor != null) + { + var filterInfo = GetFilters(controllerContext, actionDescriptor); + + try + { + var authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, + actionDescriptor); + if (authContext.Result != null) + { + // the auth filter signaled that we should let it short-circuit the request + InvokeActionResult(controllerContext, authContext.Result); + } + else + { + if (controllerContext.Controller.ValidateRequest) + { + ValidateRequest(controllerContext.HttpContext.Request); + } + + var parameters = GetParameterValues(controllerContext, actionDescriptor); + var postActionContext = InvokeActionMethodWithFilters(controllerContext, + filterInfo.ActionFilters, actionDescriptor, + parameters); + InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, + postActionContext.Result); + } + } + catch (ThreadAbortException) + { + // This type of exception occurs as a result of Response.Redirect(), but we special-case so that + // the filters don't see this as an error. + throw; + } + catch (Exception ex) + { + // something blew up, so execute the exception filters + var exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex); + if (!exceptionContext.ExceptionHandled) + { + throw; + } + InvokeActionResult(controllerContext, exceptionContext.Result); + } + + return true; + } + + // notify controller that no method matched + return false; + } + + [SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "rawUrl", + Justification = "We only care about the property getter's side effects, not the returned value.")] + private static void ValidateRequest(HttpRequestBase request) + { + // DevDiv 214040: Enable Request Validation by default for all controller requests + // + // Note that we grab the Request's RawUrl to force it to be validated. Calling ValidateInput() + // doesn't actually validate anything. It just sets flags indicating that on the next usage of + // certain inputs that they should be validated. We special case RawUrl because the URL has already + // been consumed by routing and thus might contain dangerous data. By forcing the RawUrl to be + // re-read we're making sure that it gets validated by ASP.NET. + + request.ValidateInput(); + var rawUrl = request.RawUrl; + } } } \ No newline at end of file diff --git a/IronRubyMvc/Controllers/RubyControllerDescriptor.cs b/IronRubyMvc/Controllers/RubyControllerDescriptor.cs index d121329..2284332 100644 --- a/IronRubyMvc/Controllers/RubyControllerDescriptor.cs +++ b/IronRubyMvc/Controllers/RubyControllerDescriptor.cs @@ -34,6 +34,7 @@ public override Type ControllerType public override ActionDescriptor FindAction(ControllerContext controllerContext, string actionName) { + ((RubyEngine) RubyEngine).Operations.GetMemberNames(controllerContext.Controller); var hasControllerAction = RubyEngine.HasControllerAction((RubyController) controllerContext.Controller, actionName); return !hasControllerAction ? null : new RubyActionDescriptor(actionName, this); diff --git a/IronRubyMvc/Controllers/RubyFilterInfo.cs b/IronRubyMvc/Controllers/RubyFilterInfo.cs new file mode 100644 index 0000000..f815cba --- /dev/null +++ b/IronRubyMvc/Controllers/RubyFilterInfo.cs @@ -0,0 +1,44 @@ +#region Usings + +using System.Collections; +using System.Collections.Generic; +using System.Web.Mvc; +using IronRubyMvcLibrary.Core; +using IronRubyMvcLibrary.Extensions; + +#endregion + +namespace IronRubyMvcLibrary.Controllers +{ + public class RubyFilterInfo : FilterInfo + { + public RubyFilterInfo(IDictionary filterDescriptions) + { + ParseFilters(filterDescriptions); + } + + private void ParseFilters(IDictionary descriptions) + { + var filters = descriptions.ToActionFilters(); + + AddActionFilters(filters); + AddResultFilters(filters); + } + + private void AddResultFilters(IEnumerable filters) + { + filters + .Select(filter => filter.BeforeResult.IsNotNull() || filter.AfterResult.IsNotNull()) + .ForEach(filter => ActionFilters.Add(filter)); + } + + + + private void AddActionFilters(IEnumerable filters) + { + filters + .Select(filter => filter.BeforeAction.IsNotNull() || filter.AfterAction.IsNotNull()) + .ForEach(filter => ActionFilters.Add(filter)); + } + } +} \ No newline at end of file diff --git a/IronRubyMvc/Controllers/controller.rb b/IronRubyMvc/Controllers/controller.rb index 83af918..8b2e881 100644 --- a/IronRubyMvc/Controllers/controller.rb +++ b/IronRubyMvc/Controllers/controller.rb @@ -6,19 +6,31 @@ module Filters module ClassMethods - def before_filter(name, options={}, &b) - filter(name, options.merge(:when => :before), &b) + def before_action(name, options={}, &b) + options[:before] ||= b if block_given? + options[:before] ||= name.to_sym + filter(name, options.merge(:when => :before)) end - def after_filter(name, options={}, &b) - filter(name, options.merge(:when => :after), &b) + def after_action(name, options={}, &b) + options[:after] ||= b if block_given? + options[:after] ||= name.to_sym + filter(name, options.merge(:when => :after)) end - def around_filter(name, options={}, &b) - filter(name, options.merge(:when => :around), &b) + def around_action(name, options={}, &b) + options[:before] ||= b if block_given? + options[:after] ||= b if block_given? + options[:before] ||= name.to_sym + options[:after] ||= name.to_sym + filter(name, options.merge(:when => :around)) end - def exception_filter(name, options={}, &b) + def authorize_action(name, options={}, &b) + filter(name, options.merge(:when => :authorize), &b) + end + + def exception_action(name, options={}, &b) filter(name, options.merge(:when => :exception), &b) end @@ -30,25 +42,21 @@ def after_result(name, options={}, &b) filter(name, options.merge(:when => :after_result), &b) end - def authorize_filter(name, options={}, &b) - filter(name, options.merge(:when => :authorize), &b) - end - def filter(name, options={}, &b) + def filter(name, options={}) @@action_filters ||= {} - options[:action] = b if block_given? - options[:action] ||= name.to_sym #instance_method(name.to_sym) @@action_filters[name.to_sym] = options end def action_filters @@action_filters ||= {} + @@action_filters end end def self.included(base) - base.extend(IronRubyMvc::Controllers::Filters::ClassMethods) + base.extend(ClassMethods) end end @@ -60,18 +68,19 @@ module ClassMethods def action_selector(name, options={}, &b) @@action_selectors ||= {} options[:action] = b if block_given? - options[:action] ||= instance_method(name.to_sym) + options[:action] ||= name.to_sym #class.instance_method(name.to_sym) @@action_selectors[name.to_sym] = options end def action_selectors @@action_selectors ||= {} + @@action_selectors end end def self.included(base) - base.extend(IronRubyMvc::Controllers::Selectors::ClassMethods) + base.extend(ClassMethods) end end @@ -85,9 +94,6 @@ class Controller < IronRubyMvcLibrary::Controllers::RubyController include IronRubyMvc::Controllers::Filters include IronRubyMvc::Controllers::Selectors - #cattr_accessor :action_filters, :action_selectors - - def fill_view_data instance_variables.each { |varname| view_data.Add(varname[1..-1], instance_variable_get(varname.to_sym)) } end diff --git a/IronRubyMvc/Core/Enums.cs b/IronRubyMvc/Core/Enums.cs index 5119f7f..dec75f2 100644 --- a/IronRubyMvc/Core/Enums.cs +++ b/IronRubyMvc/Core/Enums.cs @@ -5,4 +5,12 @@ public enum ReaderType File, AssemblyResource } + + public enum When + { + BeforeAction, + AfterAction, + BeforeResult, + AfterResult + } } \ No newline at end of file diff --git a/IronRubyMvc/Extensions/DictionaryExtensions.cs b/IronRubyMvc/Extensions/DictionaryExtensions.cs index fb03d8e..844d8c5 100644 --- a/IronRubyMvc/Extensions/DictionaryExtensions.cs +++ b/IronRubyMvc/Extensions/DictionaryExtensions.cs @@ -5,13 +5,20 @@ using System.Collections.Generic; using System.Web.Mvc; using System.Web.Routing; +using IronRuby.Builtins; +using IronRubyMvcLibrary.Controllers; +using IronRubyMvcLibrary.Core; +using Microsoft.Scripting; #endregion namespace IronRubyMvcLibrary.Extensions { + public static class DictionaryExtensions { + + public static RouteValueDictionary ToRouteDictionary(this IDictionary dictionary) { var rvd = new RouteValueDictionary(); @@ -33,7 +40,7 @@ public static ViewDataDictionary ToViewDataDictionary(this IDictionary dictionar return vdd; } - public static ActionSelector[] ToActionSelectors(this IDictionary dictionary) + public static IEnumerable ToActionSelectors(this IDictionary dictionary) { var selectors = new List(dictionary.Keys.Count); @@ -42,6 +49,17 @@ public static ActionSelector[] ToActionSelectors(this IDictionary dictionary) return selectors.ToArray(); } + public static IEnumerable ToActionFilters(this IDictionary dictionary) + { + var filters = new List(dictionary.Keys.Count); + dictionary.ForEach((key, value) => + { + var filterDescription = dictionary[key] as Hash; + filters.Add(new HashToActionFilterConverter(filterDescription).Convert()); + }); + return filters; + } + public static void ForEach(this IDictionary dictionary, Action iterator) { foreach (var key in dictionary.Keys) diff --git a/IronRubyMvc/Extensions/IEnumerableExtensions.cs b/IronRubyMvc/Extensions/IEnumerableExtensions.cs index 5245d79..22f0f70 100644 --- a/IronRubyMvc/Extensions/IEnumerableExtensions.cs +++ b/IronRubyMvc/Extensions/IEnumerableExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections; using System.Collections.Generic; +using Microsoft.Scripting; #endregion @@ -25,41 +26,111 @@ public static void ForEach(this IEnumerable collection, Action action) action(o); } } -// -// public static IEnumerable Collect(this IEnumerable collection, -// Func target) -// { -// foreach (var source in collection) -// { -// yield return target(source); -// } -// } -// -// public static IEnumerable Collect(this IEnumerable collection, Func target) -// { -// foreach (var o in collection) -// { -// yield return target(o); -// } -// } -// -// public static IEnumerable Zip(this IEnumerable collection) -// { -// foreach (var target in collection) -// { -// if (target.IsNotNull()) -// yield return target; -// } -// } -// -// public static IEnumerable Where(this IEnumerable collection, Func target) -// { -// foreach (var source in collection) -// { -// var tgt = target(source); -// if(tgt.IsNotNull()) -// yield return tgt; -// } -// } + + public static bool IsEmpty(this IEnumerable collection) + { + foreach (var o in collection) + { + return false; + } + return true; + } + + public static bool IsEmpty(this IEnumerable collection) + { + foreach (var o in collection) + { + return false; + } + return true; + } + + public static bool Contains(this IEnumerable collection, T value) + { + foreach (var t in collection) + { + if(t.Equals(value)) return true; + } + return false; + } + + public static bool DoesNotContain(this IEnumerable collection, T value) + { + foreach (var t in collection) + { + if (!t.Equals(value)) return false; + } + return true; + } + + public static bool DoesNotContain(this IEnumerable collection, object value) + { + foreach (var t in collection) + { + if (t == value) return false; + } + return true; + } + + public static bool Contains(this IEnumerable collection, object value) + { + foreach (var t in collection) + { + if (t.Equals(value)) return true; + } + return false; + } + + public static IEnumerable Select(this IEnumerable collection, Func predicate) + { + foreach (var source in collection) + { + if(predicate(source)) yield return source; + } + } + + public static IEnumerable Select(this IEnumerable collection, Func predicate) + { + foreach (var source in collection) + { + if (predicate(source)) yield return source; + } + } + + public static IEnumerable Collect(this IEnumerable collection, + Func target) + { + foreach (var source in collection) + { + yield return target(source); + } + } + + public static IEnumerable Collect(this IEnumerable collection, Func target) + { + foreach (var o in collection) + { + yield return target(o); + } + } + + public static IEnumerable Zip(this IEnumerable collection) + { + foreach (var target in collection) + { + if (target.IsNotNull()) + yield return target; + } + } + + public static IEnumerable Where(this IEnumerable collection, Func target) + { + foreach (var source in collection) + { + var tgt = target(source); + if(tgt.IsNotNull()) + yield return tgt; + } + } } } \ No newline at end of file diff --git a/IronRubyMvc/IronRubyMvcLibrary.csproj b/IronRubyMvc/IronRubyMvcLibrary.csproj index dcba0f4..2f71fcf 100644 --- a/IronRubyMvc/IronRubyMvcLibrary.csproj +++ b/IronRubyMvc/IronRubyMvcLibrary.csproj @@ -79,6 +79,9 @@ + + + diff --git a/IronRubyMvcWeb/App_Data/NORTHWND.MDF b/IronRubyMvcWeb/App_Data/NORTHWND.MDF index 88d20b1..5cdeb9e 100644 Binary files a/IronRubyMvcWeb/App_Data/NORTHWND.MDF and b/IronRubyMvcWeb/App_Data/NORTHWND.MDF differ diff --git a/IronRubyMvcWeb/App_Data/NORTHWND_log.ldf b/IronRubyMvcWeb/App_Data/NORTHWND_log.ldf index e9a9434..4c30e64 100644 Binary files a/IronRubyMvcWeb/App_Data/NORTHWND_log.ldf and b/IronRubyMvcWeb/App_Data/NORTHWND_log.ldf differ diff --git a/IronRubyMvcWeb/Controllers/HomeController.rb b/IronRubyMvcWeb/Controllers/HomeController.rb index 27178fc..51dd9e4 100644 --- a/IronRubyMvcWeb/Controllers/HomeController.rb +++ b/IronRubyMvcWeb/Controllers/HomeController.rb @@ -19,11 +19,17 @@ module ClassMethods end class HomeController < Controller -# def initialize(context = nil) -# if(context != nil) -# super.Initialize(context) -# end -# end + # def initialize(context = nil) + # if(context != nil) + # super.Initialize(context) + # end + # end + + before_action :my_before do |context| + $before_counter ||= 0 + $before_counter += 1 + context.request_context.http_context.response.write("Hello world") + end def index view nil, 'layout', HomeModel.new