嵌套要素文件夹层次结构中按操作名称的方法

时间:2017-01-29 11:47:20

标签: asp.net-core asp.net-core-mvc

我在这里阅读了有关功能文件夹的实现: https://msdn.microsoft.com/en-us/magazine/mt763233.aspx

我非常喜欢按功能而不是文件类型分隔的想法。我正致力于一个增强的解决方案,该解决方案允许在无限级别内构建功能层次结构。

我为此创建了一个非常简单的文件夹/文件组织逻辑。例如:

/Auth
/Auth/Login
/Auth/Login/Forgot

您可以看到顶级功能文件夹下的所有内容。在此文件夹中有特定的功能文件夹(Auth)。在那之下有一个Route子文件夹,其中包含所有控制器/视图的层次结构。

对于上面的例子,我已经实现了一个自定义路由逻辑,为我提供了这些路由:

public void Apply(ControllerModel controller)
{
   //From the article I linked before:
   controller.Properties.Add("feature", 
     GetFeatureName(controller.ControllerType));

   //My custom route value implementation:
   controller.Selectors.Clear();

   var routePath = GetRoutePath(controller.ControllerType); //"auth/login/forgot"
   var routeAttr = new RouteAttribute(routePath);
   var selector = new SelectorModel 
     { 
       AttributeRouteModel = new AttributeRouteModel(routeAttr) 
     };

   controller.Selectors.Add(selector);

}

它有效,但我不知道我做得好还是完全错了。要实现自定义路由,我只需这样做:

public class Login : Controller
{
   public IAcionResult Get()
   {
      return View();
   }

   public IAcionResult Post(LoginModel model)
   {
      return Ok()
   }
}
  • 是controller.Selectors是应用自定义路径路径的好地方吗?
  • 在添加新内容之前是否真的需要.Clear()?

我没有找到任何关于controller.Selectors的文章。

我还想实现对http方法转换的动作名称的支持,其中所有标准的http动词动作名称(get,post,put,patch,delete)自动绑定到相应的http方法过滤器。例如:

Intent intent1 = new Intent(getApplicationContext(),
                            NotificationReceiver.class);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(getApplicationContext(),
                                                          1,
                                                          intent1,
                                                          PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager1 = (AlarmManager)getSystemService(ALARM_SERVICE);
java.util.Calendar calendar1 = java.util.Calendar.getInstance();

calendar1.set(java.util.Calendar.DAY_OF_WEEK,
              Calendar.MONDAY);
calendar1.set(java.util.Calendar.HOUR_OF_DAY,
              22);
calendar1.set(java.util.Calendar.MINUTE,
              8);
calendar1.set(java.util.Calendar.SECOND,
              0);

alarmManager1.setExact(AlarmManager.RTC, calendar1.getTimeInMillis(), pendingIntent1);

我不想在我只获得/发布动作的地方使用[HttpGet]和[HttpPost]属性。我认为有一个官方解决方案,但我无法找到它。

1 个答案:

答案 0 :(得分:0)

我找到了一个效果很好的解决方案。但我不确定我刚才用这个做了什么:

    public class ActionModelConvention : IActionModelConvention
    {
        private static readonly List<String> httpVerbs;

        static ActionModelConvention()
        {
            httpVerbs = new List<String> { "GET", "POST", "PUT", "PATCH", "DELETE" };
        }

        private readonly ActionParserOptions options;

        public ActionModelConvention(ActionParserOptions options)
        {
            this.options = options;
        }

        public void Apply(ActionModel action)
        {
            var upper = action.ActionName.ToUpper();
            var found = httpVerbs.FirstOrDefault(
                     e => upper.Length >= e.Length &&
                     e == upper.Substring(0, e.Length));

            if (found != null)
            {
                //action.Selectors.Clear(); //no need to clear...I think...

                var constraint = new Microsoft.AspNetCore.Mvc.Internal //> Internal!
                    .HttpMethodActionConstraint(new String[] { found });

                var selector = new SelectorModel();
                    selector.ActionConstraints.Add(constraint);

                action.Selectors.Add(selector);
            }
        }

我认为使用Microsoft.AspNetCore.Mvc.Internal命名空间中的任何内容都不是一个好主意。但我还没有找到其他办法。

有什么想法吗?