Моя CMS для ASP.NET MVC.
У 2009-му році я повністю закінчив публікацію своеї власної CMS для ASP.NET, яку я використовував у своїх проєктах на у 2005-2009 роках - AspNet_UserManager - компонент сайта для управления пользователями. Але поступово замовники стали вимагати створювати сайти на технологіі ASP.NET MVC, яка не має нічого спільного з технологією ASP.NET, крім спільних літер у назві. Дуже прикро, що Мікрософт так загажує голови людям - спочатку робить технологію ASP, у якої доказує що лапша іх коду - коли ві пишете замість чистого коду сумісь коду та HTML - це дуже добре і взагалі единий засіб програмування. Потім у 2002-му році з'являється ASP.NET і Мікрософт декілька років та мільярди долларів витрачає на піар-компанію, чому лапша (суміш коду та HTML) це минуле WEB-програмування. А майбуте за чистим кодом, ASP.NET з чистим кодом - це справжня піонерська технологія, технологія майбутньго! А коли люди у це повірили, та перейшли на ASP.NET, витратили величезні зусілля, що до кінця свого життя працювати на ціей технологіі, наприклад зробили навіть властні CMS - Мікрософт каже, а тепер ми далі розвивати цю технологію не будемо !!! Не буде далі розвитку з декільками тегами FORM, білш якісних інструментів верстки і так далі !!! А давайте знову повернемося до 2000-х років у лапшеобразну зумісь кода і HTML !!!
І ось, залишившись з 2010 року у розбитого корита, тобто мої перші проги на ASP.NET MVC ніяк не відрізнялися від тих, хто вперше сів за компьютер у 2010-му році, хоча на старої технології ASP.NET (це перевірялось багото разів), я можу зробити за два тижня те, що роблять починаючи програмісті за рік - (завдяки зробленим за багато років наработкам, у тому числі своєї CMS), я знов на технології MVC у 2010-му році опинився на рівні починающуго програміста.
Тому однією з перших задач було зробити свою власну зручну CMS. У цьому році я починаю її публикацію. Більшість сторінок у цьому році присвячена цієї CMS, взагалі вона має:
- графічний двигун Сховище графіки на SQL FileStream та канал браузеру multipart/form-data., Загально графічні функції,
- зроблена на моему улюбленому контролі MENU із старого ASP.NET - Використання ASP.NET контролу Menu у проектах MVC.,
- має багато функцій на System.Reflection - Аналіз MVC-сайту за допомогою System.Reflection.
- має багато функцій на System.Web.Mvc.ViewEngines - Кешування вхідної сторінки сайту, DropdownList AutoPostBack у ASP.NET MVC, Компіляція MVC-проекту власним кодом за допомогою System.Web.Mvc.ViewEngines.
- має безліч різноманітних додаткових сервисів - SiteRequestTracer - Система аналізу і трасування усіх реквестів до сайту., Поштові розсилки через Gmail, глобальні параметри налаштування і так далі.
У цьому топіку я покажу як зроблена база моеї CMS.
Почнемо з меню. Я покажу сконфигуровану базу на прикладі одного мойого проэкту, де за допомогою моєї CMS сконфігуровано меню трьох рівнів доступу до функціоналу сайту - звичайний юзер, редактор контенту та супервізор/адмін.
Моя система MENU конфігурується через WEB:
Тепер подивимося детальніше. У таблиці юзерів сайту є флаг IsAdmin, який дозволяє тому чи іншому юзеру користуватися тим чи інцім рівнем доступу, та тім чи іншим MasterPage. Ось цей флаг:
А ось так формуютьcя права доступу:
Далі формуються пункти контрола MENU для кожного типу кабинету та для анонімного юзера.
І останне, що потрібно зробити - це зіставити кожний пукнт меню тому чи іншому методу контролера.
Взагалі, це невеличка частка табличок моєї CMS, наприклад є табличка з розісланим милом:
І ще багато табличок загального призначення, наприклад табличка дефолтних параметрів, з усім необхідним програмним API поновлення ціх параметрів.
Е табличка, куди збираються усі помилки сайту. І окрема табличка, де збираються помилки мультіпоточних операцій.
Табличка, де записується трасіровка усіх GET-POST реквестів
Є таблички, да зберігається графіка.
Крім табличок загального призначення, моя CMS вимагає декількох стандартних каталогів, де робиться кешировання контенту сайту:
Зараз, прямо на цієї сторінці, я покажу першу з форм цієї CMS, форму MENU, у варіанті без компіляції (на класі, описаному тут - Кешування вхідної сторінки сайту за допомогою System.Web.Mvc.ViewEngines. Але і без повної компіляції кожного VIEW це найважливіша форма, бо вона:
- Дозволяє упевнитися, що база з описом меню коректно сформована, візуально перевірити на корректність всі вище-перераховані табли - Menu, MenuRight, MenuSelector
- Дозволяє упевнитися, що всі VIEW присутні у проекті, можна побачити їх пач по діску і упевнитися, що метод контролеру вікликає саме те VIEW, що очікується
1: <%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage" %>
2:
3: <!DOCTYPE html>
4:
5: <html>
6: <head runat="server">
7: <title>Info for developer only - Customize Menu</title>
8: </head>
9: <body>
10:
11: <%Dim URI As String = "http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL")%>
12:
13: <h2>Info for developer only - Customize Menu</h2>
14:
15: <% Dim db1 As New OCMR.OCMRDataContext
16: 'собственно меню догружается классами MasterPage (MasterShared,MasterSupervisor,MasterAdmin,MasterCab) в MasterSelectItem
17: 'доступ к меню защищен в контроллерах OnActionExecuting->CabAu и дополнительно в классах MasterPage вызывается проверка прав классом MasterPageRight
18: Dim Menu = (db1.GetMenu).ToList
19: Dim AllMenuRight As System.Collections.Generic.List(Of OCMR.MenuRight) = HttpContext.Current.Application("MenuRight")
20: Dim CurUser = (From x In db1.Users Select x Where x.Email = HttpContext.Current.User.Identity.Name).ToList
21: %>
22:
23: <table border="1">
24: <thead>
25: <th>i
26: </th><th>Type
27: </th><th>NavigateUrl
28: </th><th>Text
29: </th><th>ImageUrl
30: </th><th>IsBan
31: </th><th>MenuSelector
32: </th><th>Controller
33: </th><th>Action
34: </th><th>ViewEngine
35: </th>
36: </thead>
37:
38:
39: <tr style="background-color:Silver;"><td><%: Menu(0).i%>
40: </td><td><%: Menu(0).Type%>
41: </td><td><%: Menu(0).NavigateUrl%>
42: </td><td><%: Menu(0).Text%>
43: </td><td><%: Menu(0).ImageUrl%>
44: </td><td><%: Menu(0).IsBan%>
45: </td><td><%: Menu(0).MenuSelector_i%>
46: </td><td><%: Menu(0).Controller%>
47: </td><td><%: Menu(0).Action%>
48: </td><td></td></tr>
49: <%For i As Integer = 1 To Menu.Count - 1%>
50: <% Dim Right = New OCMR.MasterPageRight
51: If Right.Check(CurUser, Menu(i).Type) Then%>
52:
53: <tr style='<%: IIf(Menu(i).Type.ToString = Menu(i - 1).Type.ToString, "background-color:white", "background-color:silver")%>'>
54: <td><%: IIf(Menu(i).i.ToString = Menu(i - 1).i.ToString, "", Menu(i).i)%>
55: </td><td><%: IIf(Menu(i).Type.ToString = Menu(i - 1).Type.ToString, "", Menu(i).Type)%>
56: </td><td><%: IIf(Menu(i).NavigateUrl.ToString = Menu(i - 1).NavigateUrl.ToString, "", Menu(i).NavigateUrl)%>
57: </td><td><%: IIf(Menu(i).Text.ToString = Menu(i - 1).Text.ToString, "", Menu(i).Text)%>
58: </td><td><%: IIf(Menu(i).ImageUrl = Menu(i - 1).ImageUrl, "", Menu(i).ImageUrl)%>
59: </td><td><%: IIf(Menu(i).IsBan.ToString = Menu(i - 1).IsBan.ToString, "", Menu(i).IsBan)%>
60: </td><td><%: IIf(Menu(i).MenuSelector_i.ToString = Menu(i - 1).MenuSelector_i.ToString, "", Menu(i).MenuSelector_i)%>
61: </td><td><%: IIf(Menu(i).Controller.ToString = Menu(i - 1).Controller.ToString, "", Menu(i).Controller)%>
62: </td><td><%: IIf(Menu(i).Action.ToString = Menu(i - 1).Action.ToString, "", Menu(i).Action)%>
63: </td>
64: <% Dim ControllerContext As New System.Web.Mvc.ControllerContext()
65: ControllerContext.RouteData = New RouteData()
66: ControllerContext.RouteData.Values.Add("controller", Menu(i).Controller)
67: If Menu(i).Action = "" Then Menu(i).Action = "Index"
68: ControllerContext.RouteData.Values.Add("action", Menu(i).Action)
69: Dim ViewEngineResult As System.Web.Mvc.ViewEngineResult
70: Dim ViewEngineError As String = ""
71: Try
72: ViewEngineResult = System.Web.Mvc.ViewEngines.Engines.FindView(ControllerContext, Menu(i).Action, Menu(i - 1).Type)
73: Catch ex As Exception
74: ViewEngineError = ex.Message
75: End Try
76: Dim ResultPath As String = ""
77: If ViewEngineError = "" Then
78: If ViewEngineResult.View IsNot Nothing Then
79: ResultPath = DirectCast(ViewEngineResult.View, System.Web.Mvc.WebFormView).ViewPath
80: End If
81: Else
82: ResultPath = ViewEngineError
83: End If%>
84: <%If ViewEngineError = "" Then%>
85: <td style='color:black'>
86:
87: <a href="<%:URI %>/<%:Menu(i).Controller %>/<%: Menu(i).Action%>" target="blank">
88: <%: ResultPath%>
89: </a>
90:
91:
92: <%Else%>
93: <td style='color:red'>
94: <%: ViewEngineError%>
95: <%End If%>
96:
97: </td></tr>
98: <%End If%>
99: <%Next%>
100: </table>
101: <br />
102: <a href='<%:URI %>/<%:viewcontext.Routedata.Values("Controller") %>/Links'>Links</a>
103: </body>
104: </html>
Моя CMS не стоїть на місці, я розвиваю ії з проекта у проект. І потрохи буду продовжувати ії публікацію.