Generate SharePoint project constants with T4 by feature definitions
Опубликовано: 25 июля, 2010 Filed under: sharepoint 1 комментарийProblem
Usually the main problem of SharePoint development is accessing SPListItem fields values by theirs internal names of field ids. For example:
SPListItem listItem = GetLIstItem(); // I prefer to use field ids for speed and garanteed way extract values listItem[SPBuiltInFieldId.Title]
The output file will be like that:
But in some scenarios fieldId doesn’t help me for get values, such as get it in item event receivers. In this case I need to know the field internal name.
public override void ItemAdding(SPItemEventProperties properties) { string toolTipFieldInternalName = ""; //oops, this place have some perfomance overhead using (SPWeb web = properties.OpenWeb()) { toolTipFieldInternalName = web.Lists[properties.ListId].Fields[toolTipFieldId].InternalName; } string urlVal = properties.AfterProperties["URL"].ToString(); SPFieldUrlValue val = new SPFieldUrlValue(urlVal); string desc = val.Description; properties.AfterProperties[toolTipFieldInternalName] = desc; }
For best experience you may install Visual T4 Editor
There is a simple way to extract and generate usefull constants for field ids and internal names from features definition files in your project with T4 mechanism built-in into visual studio:
Constants.tt (this code works fine only in Visual Studio 2010)
<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" language="C#" debug="true" hostSpecific="true" #> <#@ assembly name="Microsoft.VisualStudio.TextTemplating.Modeling.10.0.dll"#> <#@ output extension=".cs" #> <#@ Assembly Name="System.Core.dll" #> <#@ Assembly Name="System.Xml.dll" #> <#@ Assembly Name="System.Xml.Linq.dll" #> <#@ Assembly Name="System.Windows.Forms.dll" #> <#@ Assembly Name="EnvDTE" #> <#@ import namespace="System" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Diagnostics" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Xml.Linq" #> <#@ import namespace="System.Collections" #> <#@ import namespace="System.Reflection" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="EnvDTE" #> <#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> <# var currentDirectory = Path.GetDirectoryName(Host.TemplateFile); var xmlFiles = Directory.GetFiles(currentDirectory, "*.xml", SearchOption.AllDirectories); var fieldQualifier = XName.Get("Field", "http://schemas.microsoft.com/sharepoint/"); var listdQualifier = XName.Get("ListInstance", "http://schemas.microsoft.com/sharepoint/"); #>using System; namespace <#= System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint") #> { public static partial class Constants { public static class Fields { <# var fields = xmlFiles .Select(XDocument.Load) .Select(d => d.Descendants(fieldQualifier)) .SelectMany(x => x) .Where(i => i != null) .Select(i => new KeyValuePair<string, string>( i.Attribute("ID") != null ? i.Attribute("ID").Value : null, i.Attribute("Name") != null ? i.Attribute("Name").Value : null)) .Where(i => !string.IsNullOrEmpty(i.Key) && !string.IsNullOrEmpty(i.Value)) .Distinct(); foreach (var field in fields) { #> public static string <#= field.Value #>_InternalName = "<#= field.Value #>"; public static Guid <#= field.Value #>_Id = new Guid("<#= field.Key #>"); <# } #> } public static class Lists { } } }
The output file will be like follow:
using System; namespace MyProjectNameSpace.Project1 { public static partial class Constants { public static class Fields { public static string DocKind_InternalName = "DocKind"; public static Guid DocKind_Id = new Guid("{b4fc3e5e-7573-4e39-9417-81d85f25ed73}"); public static string RegDate_InternalName = "RegDate"; public static Guid RegDate_Id = new Guid("{e453a0ee-7797-4d90-941c-0ea9a775f48d}"); public static string RegUser_InternalName = "RegUser"; public static Guid RegUser_Id = new Guid("{616997f5-6cf2-4795-b625-d7b7f4681a2e}"); } public static class Lists { } } }
Презентации с выступлений на прошлой неделе
Опубликовано: 24 мая, 2010 Filed under: sharepoint, Uncategorized Оставьте комментарийНа прошлой неделе состоялось 2 очень значимых для меня мероприятия:
- SPConf — SharePoint Conference Russia 2010 http://rusug.net/spconf.
- ReMIX — ReMIX http://remix.ru.
На обоих мероприятиях мне посчастливилось выступать. Очень доволен как организацией, так и новыми знакомствами. Если кому-то интересно, выкладываю здесь свои материалы (пока только слайды, чуть позже будут ещё и видео) с обоих выступлений.
SharePoint and oData
Опубликовано: 11 апреля, 2010 Filed under: oData, sharepoint, SharePoint 2010 | Tags: oData, sharepoint 2 комментарияВ SharePoint 2010 многое сделано для открытости доступа к данным, в том числе поддержка oData. Клиентская модель построена поверх этих возможностей.
Для того, чтобы опробовать возможности SharePoint oData в действии вам достаточно вызвать сервис ListData:
http://[serverName]/_vti_bin/ListData.svc
Если в результате получите ошибку 404, то скорее всего у вас не стоит ADO.NET Data Services v1.5 CTP2
Далее можно попробовать воспользоваться Visual Studio
В результате получить довольно-таки неоднозначные в связи с локалью богатые возможности:
class Program { static void Main(string[] args) { var context = new ClientDataContext(new Uri("http://localhost/_vti_bin/ListData.svc")); context.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials; var результат = context.ДокументыПроекта.Где(x => x.Имя != null).ToList(); } } public static class Расширения { public static IEnumerable<T> Где<T>(this IEnumerable<T> source, Func<T, bool> predicate) { return source.Where(predicate); } }
Ну или просто возможность работы из браузера:
А так же из Excel, благодаря PowerPivot.
SharePoint Business Connectivity Services: Новые возможности
Опубликовано: 23 марта, 2010 Filed under: Uncategorized | Tags: BCS, BDC, sharepoint, SharePoint Designer, SQL Server, visual studio, WCF 1 комментарийЗаписал скринкаст по Business Connectivity Services.
- Принципы построения интеграционных решений на SharePoint
- Работа с внешними данными
- Демонстрация возможностей SharePoint BCS.
- Обсуждение принципов работы, дистрибуции и потенциала платформы.
- Демонстрация примеров работы с сервисом.
7й подкаст Петербургской группы ALT.NET
Опубликовано: 22 марта, 2010 Filed under: Podcast | Tags: architecture, CQRS, DDD, Domain-Driven Design, Podcast Оставьте комментарийDomain-Driven Design и CQRS
Ведущий: butaji
Наши гости: frozen_space и chaliy
Содержание:
- Что значат все эти буквы, стоит ли изучать?
- Список литературы
Applying Domain-Driven Design and Patterns: With Examples in C# and .NET http://www.amazon.com/Applying-Domain-Driven-Design-Patterns-Examples/dp/0321268202
Yahoo group Domain-Driven Design http://tech.groups.yahoo.com/group/domaindrivendesign/
http://www.infoq.com/minibooks/domain-driven-design-quickly
http://www.domaindrivendesign.org/
CQRS à la Greg Young http://blog.fohjin.com/blog/2009/11/12/CQRS_a_la_Greg_Young
- Насколько DDD реально имеет место в проектах?
- Действительно ли DDD помогает управлять сложностью?
- Сколько паттернов вы запомнили из книги Ивенса?
- CQRS — недостаAтки и преимущества
- OpenSource примеры
DDDSample http://dddsample.sourceforge.net/
S#arp Architecture http://code.google.com/p/sharp-architecture/
6й подкаст Петербургской группы ALT.NET
Опубликовано: 16 марта, 2010 Filed under: .net, Podcast | Tags: .net, C#, community, ineta, сообщество 3 комментарияСообщества Разработчиков
Ведущие: Дмитрий Нестерук и Виталий Баум
Наши гости: Владимир Юнев и Евгений Жарков
Сообщества в рунете
За пределами рунета
Подкасты Петерубргской Группы Alt.NetПодкасты о разработке в среде .Net. Ключевые слова: C#, F#, Boo, Visual Studio, .Net, PostSharp, Asp.Net личная подкаст-лента Петербургская Группа Alt.Net (подробнее, RSS-поток) |
5й подкаст Петербургской группы ALT.NET
Опубликовано: 28 февраля, 2010 Filed under: Podcast | Tags: Podcast, S.O.L.I.D., scrum, tdd, xp Оставьте комментарий
SOLID & TDD и прочие показатели качества кода
Наши гости: Alexander Byndyu и Vitaly Stakhov
SCRUM & XP
- http://ru.wikipedia.org/wiki/Scrum
- http://ru.wikipedia.org/wiki/Экстремальное_программирование
- http://www.infoq.com/minibooks/scrum-xp-from-the-trenches
OOD: Best practicies
- Single Responsibility Principle
- Open/Closed Principles
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
TDD: Best Practicies
- Mocks aren’t stubs
- xUnit.NET, NUnit, MbUnit, и та утилита, от Microsoft, которую не смог вспомнить Александр
Ещё говорили о
Подкасты Петерубргской Группы Alt.NetПодкасты о разработке в среде .Net. Ключевые слова: C#, F#, Boo, Visual Studio, .Net, PostSharp, Asp.Net личная подкаст-лента Петербургская Группа Alt.Net (подробнее, RSS-поток) |
4й подкаст Петербургской группы ALT.NET
Опубликовано: 20 февраля, 2010 Filed under: ALT.NET, Podcast | Tags: .net, ALT.NET, asp.net mvc, css3, Разработка, FubuMVC, html5, javafx, mvc, Podcast, RIA, RoR, silverlight, spbalt.net, visual studio 1 комментарийВсё, что вы хотели узнать о ASP.NET
Что нового в ASP.NET MVC2.
- Асинхронные контроллеры
- Зоны (areas)
- Валидация через data annotation
- Строго-типизированные хелперы
- Хелпер-темплейты, параметры по-умолчанию
Альтернативные view engines
Удобен ли Visual Studio для веб-разработки
- Новое понимание MVC. Другой контроллер. Конвенции.
Почему я уйду на Ruby on Rails / Django
Как хорошо работать с Asp.Net AJAX и jQuery
HTML5 + CSS3 (@font-face)
- font-face на js — cufon http://wiki.github.com/sorccu/cufon/about
RIA
- Олимпиада 2010, Silverlight, Windows 7 Phone, JavaFX
Создавать ли View для iPhone
Подкасты Петерубргской Группы Alt.NetПодкасты о разработке в среде .Net. Ключевые слова: C#, F#, Boo, Visual Studio, .Net, PostSharp, Asp.Net |
Альтернативный MVC Framework на ASP.NET: FubuMVC
Опубликовано: 16 февраля, 2010 Filed under: ALT.NET, asp.net, asp.net mvc | Tags: ALT.NET, asp.net, FubuMVC, IoC, mvc, SoC, Spark, StructureMap, ViewEngine 9 комментариевВведение
Почему же альтернативный? Всё просто, данный framework пишется силами выдающихся участников ALT.NET community, а именно:
Jeremy Miller, Chad Myers, Mark Nijhof, Ryan Kelley, и Joshua Flanagan.
FubuMVC не имеет никакого отношения к ASP.NET MVC Framework, кроме того, что так же построен поверх ASP.NET и реализует паттерн Front-Controller. Название FubuMVC строится из акронима “For us by us” и аббривеатуры MVC (кто ещё не знает, что это значит Model-View-Controller ?). Проект был инициирован по причине недовольства вышеперечисленных личностей архитектурными решениями, принятыми в ASP.NET MVC. Сказать, по правде, по прошествии года, после старта проекта, он не утратил своей элегантности и простоты в подходах.
FubuMVC вносит несколько непривычное понимание Controller’а. Теперь это не просто некоторый класс, теперь это больше логическая связность некоторых методов. Это раскрывает более широкие возможности для настройки специфичного поведения Controller’а, к примеру, обработки ошибок, реализации правил кэширования, определения типа возвращаемых значений. К тому же возможность динамического объединения вызовов Action’ов уже является удобным механизмом к расширению. Далее мы более подробно поговорим об особенностях этой реализации в FubuMVC.
В качестве View Engine (в данном случае является лишь определением и не имеет отношения к ASP.NET MVC View Engine) используется механизм рендринга WebForms (проще говоря FubuPage, которая является View в FubuMVC, наследует от System.Web.UI.Page), но имеется возможность в подключении всех существующих в ASP.NET MVC ViewEngine’ов, примером тому может быть реализация SparkViewEngine.
Конечно же уместным будет вопрос, а зачем же нужен “другой” MVC Framework, с меньшим количеством участников проекта, с меньшим вниманием со стороны разработчиков, с меньшим количеством тестеров и прочими атрибутами mainstream проектов.
В основу проекта FubuMVC его создатели заложили больше возможностей для кастомизации проекта под прикладные нужды, а так же конвенциям (соглашениям) относительно настройки и расширяемости. Причём конвенции должны покрывать основные и типичные нужды приложения, коих в разработки решений достаточно большое количество. Какие-либо дополнительные разработки будут инициировать собой появление дополнительных модулей.
Аналогичные конвенции (соглашения) существую в известном всем MVC Framework на Ruby: Ruby On Rails. На своей практике разработки под Ruby On Rails я неоднократно убеждался, что данные конвенции действительно позволяют снизить сложность и количество написанного кода. Примером тому может служить ORM Active Record с его соглашениями касательно преобразования объектов в таблицы реляционной базы данных, а так же соглашение, относительно хранения конфигурации в формате YAML.
Официальный сайт проекта: http://fubumvc.com/
FubuMVC на GitHub: http://github.com/darthfubumvc/fubumvc
Первое погружение
Начнём с конвенций именования и структуры проекта. Вся работа с настройкой приложения FubuMVC ведётся через некоторый DSL, стиль конфигурирования очень близок к работе с FluentNhibernate.
public class HelloWorldFubuRegistry : FubuRegistry { public HelloWorldFubuRegistry() { IncludeDiagnostics(true); Applies.ToThisAssembly(); Actions .IncludeTypesNamed(x => x.EndsWith("Controller")); Routes .IgnoreControllerNamespaceEntirely() .ConstrainToHttpMethod(action => action.Method.Name.EndsWith("Command"), "POST") .ConstrainToHttpMethod(action => action.Method.Name.StartsWith("Query"), "GET"); Views .TryToAttach(x=> { x.to_spark_view_by_action_namespace_and_name(GetType().Namespace); x.by_ViewModel_and_Namespace_and_MethodName(); x.by_ViewModel_and_Namespace(); x.by_ViewModel(); }); Output.ToJson.WhenCallMatches(action => action.Returns<AjaxResponse>()); HomeIs<HomeInputModel>(); } }
Исходя из данной конфигурации IoC-container’а нетрудно догадаться о следующем:
- Все классы, оканчивающиеся на “Controller” будут зарегистрированны в качестве Controller
- Все запросы, оканчивающиеся на “Command” должны будут приниматься POST’ом, а начинающиеся на “Query” GET’ом
- Все View будут заполняться соответствующими по именованию ViewModel
- Весь вывод, возвращающий тип AjaxResponse будет серилизоваться в JSON
В качестве IoC-container’а в FubuMVC выбран StructureMap. Выбор не случаен, т.к. фактически StructureMap является старейшим IoC/DI-container’ом. Начало разработки датировано июнем 2004ого года и велось Jeremy D. Miller, так же и участником проекта FubuMVC.
Второе погружение
Давайте рассмотрим несколько примеров приложений на FubuMVC
Первое из них http://github.com/DarthFubuMVC/fubumvc-examples/tree/master/src/Actions/ControllerActionStyle/
Начнём, с того, что проверим его работоспособность:
В namespace’е SimpleWebsite.Core определена наша модель предметной области, а именно Movies, работе с которыми и просвещенно приложение.
В SimpleWebsite.Controllers определен единственный Controller и View, работу которых мы и видим на рисунке выше.
Давайте разберемся с MoviesController. Судя по его конструктору нетрудно догадаться, что DependencyInjection мы получаем out-of-box без каких-либо переопределений Controller Factory:
private readonly IRepository _repository; public MoviesController(IRepository repository) { _repository = repository; }
Метод List() является “списочным” и предоставляет нам доступ к ViewModel
public ListMoviesViewModel List() { return new ListMoviesViewModel {Movies = _repository.Query<Movie>()}; }
Стоит обратить внимание на конвенцию именования в данном случае. Под ViewModel (читается так же как PresentationModel) понимается адаптированная для представления модель, что подчеркивает SoC в реализации FubuMVC. View в данном случае будет строго типизировано на этот тип:
public class List : FubuPage<ListMoviesViewModel> <br />{}
Метод Add() попадает под правило обработки AjaxResponse, следовательно вернется на страницу в виде JSON, где будет радужно встречен jQuery обработчиком.
Аналогичная ситуация с методом Remove().
Стоит обратить внимание на конвенцию именования принимаемых данными методами типов:
AddMovieInput, RemoveMovieInput
Наименования данных классов указывают на направление данных, т.е. их ввод с запросом. С помощью этих типов на View мы определяем Url для обработки соответствующих Action’ов Controller’а:
<%= Get<IUrlRegistry>().UrlFor(new AddMovieInput()) %>
FubuMVC реализует 3 модели обработки запросов:
- Controller / Action Привычный для ASP.NET MVC Framework способ. Определяется некоторый тип — Controller, который содержит в себе соответствующие методы — Action’ы. Данный пример был рассмотрен выше.
- Controller-less Actions (HandlerStyle) Данный способ подразумевает под собой “обезличенные” Action’ы. т.е. без привязки к какому-либо Controller’у. Правила нахождения Action’ов описываются Policy, которые можно описывать и добавлять в коде.
- REST-like (EndPointStyle) Этот способ близок к предыдущему, однако, в отличии от него реализует не только метод Execute, а все методы, необходимые для REST взаимодействия, каждый метод Get(), Post(), Put(), Head() в дальнейшем будет соответствовать типу HTTP запроса:
var httpVerbs = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) {"GET", "POST", "PUT", "HEAD"};
Погружаемся далее
Как вы уже догадались, FubuMVC славится своими возможностями для расширения. Предлагаю ознакомиться с ещё одним примером: http://github.com/DarthFubuMVC/fubumvc-examples/tree/7c4b2165aedb6754a01538aee956e29d4060654c/src/Outputs/VaryByAcceptHeader
В данном примере рассматривается вариативность формата возвращаемых данных от параметра запроса, причём вы можете с легкостью добавить новый формат данных.
Этот пример практически ни чем не отличается от рассматриваемого, раннее, за тем лишь исключением, что в классе
VariableOutputConvention : IConfigurationAction
мы регистрируем интересующие нас возвращаемые типы, а так же указываем дополнительный Behavior для рендринга страницы:
RenderVariableOutput : BasicBehavior
После чего достаточно только заполнить интересные вам Movies http://localhost:59187/movies/list и попросить вернуть их в JSON http://localhost:59187/movies/list?renderformat=json или в XML http://localhost:59187/movies/list?renderformat=xml
Данный пример наглядно иллюстрирует точки расширения FubuMVC для любых нужд.
Диагностика
По адресу http://localhost:59187/_fubu вас будет ждать небольшой сюрприз, а именно – диагностическая утилита для FubuMVC.
C её помощью вы сможете просматривать все зарегистрированные в вашем приложении
- Chains – цепочки поведения, так называются логические связи между маршрутами и Action’ами. О цепочках можно посмотреть все обертки и возвращаемые значения.
- Routes – показывает все зарегистрированные маршруты, и связанные с ними Action’ы, тип выводимых данных и цепочки поведения.
- Actions – зарегестрированные в приложении Action’ы, их маршруты и возвращаемые значения
- Inputs – возможные типы и способы ввода в вашем приложении со стороны запросов
Заключение
При первом и поверхностном знакомстве проект FubuMVC не показался мне чем-то выдающимся. Однако в последнее время мой интерес к нему постоянно растёт. Я считаю, что FubuMVC является более удобным и гибким инструментом, по сравнению с ASP.NET MVC. Однако это ещё не значит, что я уже готов доверить данному проекту свои коммерческие проекты. Тот факт, что сообщество всё же поддерживает многообразие качественных решений для создания приложений на ASP.NET, может только радовать.
Материалы
FubuMVC Contrib http://code.google.com/p/fubumvc-contrib/
Front Controller http://msdn.microsoft.com/en-us/library/ms978723.aspx
FubuMVC — Front Controller style framework http://blog.fohjin.com/blog/2009/2/21/FubuMVC_Front_Controller_style_framework
FubuMVC Google Group http://groups.google.com/group/fubumvc-devel?pli=1
Ещё один MVC Framework на ASP.NET OpenRasta http://trac.caffeine-it.com/openrasta
Соглашение относительно настройки http://msdn.microsoft.com/ru-ru/magazine/dd419655.aspx