• Авторизация


Implementing security policy for your applications (part 3) (secondly, not rant) 23-01-2005 03:05


До сих пор рассматривались ситуации, основанные на наследовании permissions on stack downstream. The mechanism that enables any callee on the stack to narrow its permissioms was described. In fact, however, there is a situation, when it is impossible to consistently inherit permissions downsteam. For example, calling any native API will ultimately require Unmanaged permission, но нелепо требовать этого от всех components in current call, but only most trusted libraries. To hahdle this condition, CLR provides CodeAccessSecurity class with Assert() method. By calling Assert() the caller sets the watermark on the frame upon witch the security permissions are not evaluated. This means, in particular, that the caller may not nave the required permissions, but sequencial Demand() on the stack will succeed. To perform Assert() the caller itself must pass the security validation for particular permission. One grants such a permission to specific code in policy.
Ну, вот. Если с Assert'ом разобрались, то пережде чем перейти к практике, осталось привести табличку наиболее часто используемых build-in permissions из CLR 1.1.
В левой колонке - имя класса permission, в правой - контролируемые операции.





















SecurityPermission Execution, UnmanagedCode, Assertion etc.
FileIOPermission Read, Write, Append, Path Disc.
EventLogPermission Browse, Audit, Instrument
RegistryPermision Read, Write, Create
SqlClientPermission

Стоит ли говорить, это все классы, упомянытые здесь в левой колонке (да с ними еще с десяток, используемых реже) - все наследуют от рассмотернной ниже жемчужины - CodeAccessPermission?
Теперь простой пример (по пути к Feeder'ам): kод загружает assembly, с намерениями вызвать некоторый метод. Код разрешает вызов метода только если соответсвующий policy опеределяет для загруженного assembly, как минимум, execute permission. Сам код выглядит так:


string strAssemblyFile = "file://" + strCodeBase;
Assembly fAsm = Assembly.LoadFrom(strAssemblyFile);

PolicyLevel polLevel = SecurityManager.LoadPolicyLevelFromFile(@"xxx.config", PolicyLevelType.AppDomain);
PolicyStatement statement = polLevel.Resolve(evidence);
PermissionSet ps = statement.PermissionSet;

IPermission perm = new SecurityPermission(SecurityPermissionFlag.Execution);
PermissionSet requiredPS = new PermissionSet(PermissionState.None);
requiredPS.AddPermission(perm);
bool bRes = requiredPS.IsSubsetOf(ps);
if( !bRes )
{
Console.WriteLine("Assmebly {0} has not granted the execution permission", strCodeBase);
return;
}


Допустим, сам policy имеет, для просты дела, такую top CodeGroup:
<CodeGroup
class="FirstMatchCodeGroup"
version="1"
PermissionSetName="Nothing">
<IMembershipCondition
class="AllMembershipCondition"
version="1"
/>
<CodeGroup class="UnionCodeGroup"
version="1"
PermissionSetName="Execution" >
<IMembershipCondition class="UrlMembershipCondition"
version="1"
Url="codebase"/>
</CodeGroup>
</CodeGroup>
Соответствующий PermissionSet (named "Execution") выглядит так :
<PermissionSet
class="NamedPermissionSet"
version="1"
Name="Execution">
<IPermission
class="SecurityPermission"
version="1"
Flags="Execution"
/>
</PermissionSet>
Если запустить приведенный код через такой policy, то загруженный assembly пройдет security check. Из-за второго, вложенного элемента CodeGroup, кот. связывает его Url с SecurityPermission.ExecutionFlag. Разумеется, codebase, кот. используется в LoadFrom() (на его основе, как следует из поста 2, создается Evidence), должен быть таким же, как и в UrlMembershipCondition из этого CodeGroup.
комментарии: 0 понравилось! вверх^ к полной версии
Rules for life, Commented. For Havi. 22-01-2005 23:45


Rule 1: Life is not fair. Get used to it. :nud::confuse:


Rule 2: The world won't care about your self-esteem. The world will expect you to accomplish something before you feel good about yourself.


Rule 3: You will NOT make $40,000 a year right out of high school. You won't be a vice-president with a car phone, until you earn both.


Rule 4: If you think your teacher is tough, wait till you get a boss. He doesn't have tenure.


Rule 5: Flipping burgers is not beneath your dignity. Your grandparents had a different word for burger flipping; they called it opportunity.


Rule 6: If you mess up, it's not your parents' fault. Don't whine about your mistakes -- learn from them.


Rule 7: Before you were born, your parents weren't as boring as they are now. They got that way from paying your bills, cleaning your clothes and listening to you talk about how "cool" you are. So before you save the rain forest from the parasites of your parents' generation, try "delousing" the closet in your own room.


Rule 8: Your school may have done away with winners and losers, but life has not. In some schools they have abolished failing grades; they'll give you as many times as you want to get the right answer. This doesn't bear the slightest resemblance to anything in real life.


Rule 9: Life is not divided into semesters. You don't get summers off and very few employers are interested in helping you find yourself. Do that on your own time.


Rule 10: Television is NOT real life. In real life people actually have to leave the coffee shop and go to jobs.


Rule 11: Be nice to nerds. Chances are you'll end up working for one.

комментарии: 0 понравилось! вверх^ к полной версии

Implementing security policy for your applications (part 3) (firstly rant) 22-01-2005 23:13


Можно перевести дух. У нас впереди еще Assert() и живой пример использования CAS в Feeder'ax. Meanwhile, some citations about predictions for 2005 and blogging:
" ... 2) Several executives will get fired for NOT blogging. Why? Blogging helps get adoption and executives who don't get adoption will be cut. They might not be told it was for not blogging, but watch who replaces the execs who are ousted.

3) Several more people will get fired FOR blogging. Another one was reported today. Or worse yet, will get sued for what they write or do on their blogs. Blogging is dangerous business."
Автор - Scoble
А вот и еще один.
Что касается меня, то я не поставлю ни шекеля ни на FireFox(The Brower, Reloaded), ни на Safari. Ув. Don, мне ли рассказать вам, что malware наводятся на цели именно в зависимости от их market share? :)
Есть еще такая фишка - tabbed-browsing. Господа маркетологи, я понимаю, что не все из вас имеют техническое образование, но лучше бы тогда уж вам продавать примочки от Google. Помяните мое слово, как prediction: если Google и вправду вкладывает деньги в разработку своего browser, у вас будет сразу 3(!) совершенно бесполезных вещи на рынке. И все с tabbed-browsing. Будь я на месте разработчиков из Mozilla, я бы для вас заранее и продуманно выделил отдельный tab, куда можно было бы быстро сливать ваши rant'ы .
Относительно Eclipse, Mr. Sessions еще года 3 тому предупреждал, что иллюзии java-истов о единой платформе ну никак не согласуются с мнениями советов директоров в Sun и в IBM. Да еще и BEA тут под ногами все это время путалась. Одним словом, на мой взгляд, это будет правильный шаг со стороны Sun - купить, да и дело с концом. Но в свои predictions я это не могу выдвинуть.
комментарии: 0 понравилось! вверх^ к полной версии
Implementing security policy for your applications (part 2) 22-01-2005 17:17


В прошлый раз мы получили PermissionSet . Теперь разберемся, как его использовать.

Во-первых, PermissionSet наследует ICollection, каждый из элементов которой, как минимум, имплементирует IPermission. Об этом интерфейсе и пойдет речь ниже. Сам PermissionSet определяет т.наз. "операции множеств" (set operations), но не над отдельными элементами из своей коллекции, а над самими PermissionSets, позволяя об'единять и разбивать их на новые коллекции. Таким образом, каждая коллекция PermissionSet состоит из элементов, поддерживающих IPermission и имеет методы - Union(), Intersect(), IsSubsetOf() -, позволяющие строить новые множества. Прежде, чем мы займемся IPermission, обратим внимание на то, это среди поддерживаемых в System.Collections namespace, нет похожей на ISet, и поэтому можно считать, что определение подобных операций для множеств, представляется логичным компромиссом для архитектуры CLR 1.1.
Ввиду отсутствия ISet, тот же design применяется и к IPermission, позволяя об'единять и пересекать их между собой. В этом посте речь не идет о collections design в CLR, но я бы хотел подчеркнуть, что имплементация этих методов is type-specific, т.е. сам имплементор решает, с кем ему пересекаться и об'единяться. Например, будет ошибкой послать FileIOPermission в WebPermission.Intersect().
Помимо методов для множественных операций, IPermission имеет метод Demand(), ради которого, собственно, он и задумывался. Самое простое использование Demand() состоит в следующем : ваш код желает требовать от callers соответствующих permissions. Это желание можно выразить так:

a). Построим те permissions, кот. потом будем требовать

FileIOPermissionAccess readAccess = FileIOPermissionAccess.Read;
IPermission p = new FileIOPermission(readAccess, @"c:okey");

b). Затребуем от всех callers выше по стеку иметь такой же permission из их PermissionsSets или где там они их будут брать.
p.Demand();

The Demand() method triggers a stack walk in which the permissions of every method are inspected. The CLR calculates the permissions of each method by running the evidence from the method's assembly through the security policy - see my previous post. If at least one method on the stack does not have the permission being demanded, then the Demand() method will throw a SecurityException. If, however, all the methods on the stack do have the permission being demanded, then the Demand() method will indeicate this by not throwing the exception.

Всякий раз, когда дело доходит до stack, я вспоминаю обложку "Programming Windows Security" by Keith Brown,
но и сегодня будем только облизываться - всему свое время. (Кстати, для не посетивших PDC 2003 в LA - это must все от того же Keith Brown).

Так вот Demand(), как правило, инициализирует StackWalk. Поскольку это интерфейсный метод, то, в принцине, каждый имплементор сам решает, where you want to walk. Большинство классов CLR отправляются именно на stack. Вот, например, как может выглядеть GetHostByName() implementation (потом заменю на что-нибудь более интересное из ADSI):
public static IPHostEntry GetHostByName(string host)
{
// enforce policy through StackWalk
DnsPermission perm = new DnsPermission(PermissionState.Unrestricted);
perm.Demand();
// if we get here, all callers on the stack have DnsPermission
// ... perform the actual work
}
Это пример т.наз. imperative security demand. Тот же пример может быть переписан и так:
[DnsPermission(SecurityAction.Demand, Unrestricted=true)]
public static IPHostEntry GetHostByName(string host)
{
// if we get here, all callers on the stack have DnsPermission
// ... perform the actual work
}
Этот стиль называется declarative. Главное его преимущество в том, что с его помощью можно узнать о security requiremenets методов из metadata, не запуская код.
Самому же проходу по stack, не осталось почти никакой работы, кроме как вызвать ps.IsSubsetOf() у проверяемого permission для всех методов, разузнав их PermissionSets из соответствующего assembly через его evidence - см. пред.post.
Вот так о одном месте сходятся design of permission's set operations ( IsSubsetOf() ), design of evidence ( получение Assembly.Evidence ), и наконец, Demand() enforcement.

Не спуская глаз с этой жемчужины CLR, нужно еще и вспомнить о классе CodeAccessPermission уже хотя-бы по той причине, что именно в нем эта жемчужина и лежит. А именно, этот класс реализует IPermission и еще довабляет к нему виртуальные методы Deny(), PermitOnly(), Assert() и группу RevertXXX(). Относительно PermitOnly() - его предназначение в том, чтобы дать возможность
Читать далее...
комментарии: 0 понравилось! вверх^ к полной версии
Implementing security policy for your applications (part 1) 20-01-2005 14:47


Не могу сказать, чтобы я до конца понимал CAS, поэтому этот post останется (пока) на уровне "так принято". До kibitzing мой CAS еще не поднялся.
Итак, главное, что необходимо понимать для поддержки собственного security policy, это "the result of running a body of evidence through a security policy is a permission set". Т.е. CLR предлогает следующих путь :
a) ваш app читает security policy definition из своего XML,
b) грузит(load) assembly, кот. нужно проверить,
c) получает его evidence ( или вместо b) и c) создает evidence по assembly codebase )
d) пропускает этот evidence через прочтенный security policy.
Важно помнить, что в CLR security policy определяется на 4-х уровнях (levels) : User, Machine, Enterprise, AppDomain. Первые три уровня загружаются автоматически при старте CLR. Редактировать их можно или из caspol.exe или из MMC snap-in. Для вашего приложения остался уровень AppDomain, кот. никак не загружается самим CLR, а предназначен именно для целей application security policy. Первоначальный XML с вашим security policy definition лучше всего скопировать из существующих (security.config - для Machine level, enterprise.config - для Enterprise level).
Вот как может выглядеть ваш код, кот. исполняет первый шаг - а) чтение из своего XML:
PolicyLevel polLevel = SecurityManager.LoadPolicyLevelFromFile(@"...xxx.xml", PolicyLevelType.AppDomain);
Как видим, всю работу по разборке и загрузке соответствующих внутренних классов производит SecurityManager. Это довольно непростой процесс, учитывая то, как устроены отношения внутри security policy - CodeGroups со своими membership conditions etc. Возможно, это тема для отдельного post'a.
[ комментарий за 24.01
CodeGroups определяются иерархически, позволяя присвоить одному assembly различные PermissionSets. Каждый CodeGroup имеет двоякое предназначение - с одной стороны, он связывает controlled assembly(ies) с PermissionSet, а с другой - он использует интерфейс IMembershipCondition для проверки принадлежности controlled assembly к этому CodeGroup. IMembershipCondition имеет метод Check(), которым и дается эта проверка. Имплементация Check() очень разнится в зависимости от класса, кот. реализовывает IMembershipCondition. Например, UrlMembershipCondition использует URL from evidence для этой проверки, тогда как, например, StrongNameMembershipCondition делает это с помощью testing its strong name. Обратим внимание и на AllMembershipCondition class that simplu that matches all code.
Среди наиболее часто используемых реализаций CodeGroup, нужно обратить внимание на UnionCodeGroup class, that represents a code group whose policy statement is the union of the current code group's policy statement and the policy statement of all its matching child code groups. Все implementations of CodeGroup используют abstract class (not interface) CodeGroup

]
Пока же первый шаг выполнен - ваш security policy прочитан и загружен.
[комментарий за 24.01
Для поддержки permission serialization to and from XML, существует интерфейс ISecurityEncodable, со своими ToXml() и FromXml() методами.
]
Загрузка проверяемого assembly для шага не представляет никакого труда:
Assembly assm = Assembly.LoadFrom(@"....dll");
Равно, как и получение его evidence:
Evidence evidence = assm.Evidence;
Остался последний шаг - пропустить его через полученный на первом шаге policy level. И здесь код не вызывает много вопросов:
PolicyStatement statement = polLevel.Resolve(evidence);
PermissionSet permSet =statement.PermissionSet;
Тот же Resolve() имеется и у CodeGroup, позволяя пропустить evidence через policy только частично.
Кстати, то же самое можно сделать, и не загружая самого assembly, если уметь построить evidence по codebase:
Evidence evidence = new Evidence();
evidence.AddHost(new Url(codebase));
evidence.AddHost(Zone.CreateFromUrl(codebase));
try{
evidence.AddHost(Site.CreateFromUrl(codebase));
}
catch(ArgumentException} { ... }
PolicyStatement statement = polLevel.Resolve(evidence);
Относительно PolicyStatement надо сказать еще несколько слов. Этот класс нужен из-за того, что итоговый (final) PermissionSet должен еще вычисляться, принимая во внимание, на каком уровне вложенности находится соответсвующий CodeGroup. Final PermissionSet дается только при условии
PolicyStatement.Attribute == PermissionStatementAttribute.LevelFinal
SecurityManager имеет статический метод ResolvePolicy(), кот. решает этот вопрос сразы для всех уровней:
Permissionset ps = SecurityManager.ResolvePolicy(evidence);
Обратим внимание, это этот метод уже возвращает именно искомый и окончательный (final) PermissionSet.
комментарии: 0 понравилось! вверх^ к полной версии
Reports with Custom Assemblies Preview 13-01-2005 13:56


Module that actually process reports - Microsoft.ReportingServices.Processing -вызывается как из VS Designer'a, так из самого Report Server'a. Его ReportProcessing.ReportObjectModel and ReportProcessing.ExprHostObjectModel
namespaces представляют особый интерес, т.к. они expose Report Object Model to the reports. Те Constants, Globals, Parameters etc. collections, кот. видны в Designer'e - берутся именно отсюда. Очень интересен также класс User из ReportObjectModel. Это пользователь, кот. на самом деле обратился за получением report.
Ясное дело, что все эти collections могут быть переданы в custom assembly как параметры. Ясно также, что они read-only, и нельзя изменить параметры report из custom assembly.
Иногда нужно не давать возможности какому-то пользователю запрашивать report с определенными параметрами, т.е. сравнить User!UserID и Parameters collection. Так и хочется спросить - а где же BRE? Но нету в RS еще такого зверя! Сравниваем в ручную. Например, с базой.
Установки соедениния с базой нужно хранить для Designer'a в devenv.exe.config (У меня пол-дня заняло понять, почему. Я-то думал, что Studio не сам будет загружать Microsoft.ReportingServices.Processing, а попросит это сделать Report Service), а для deployed reports - в web.config, кот. расположен в $:Program FilesMicrosoft SQL ServerMSSQLReporting ServicesReportServer.
комментарии: 0 понравилось! вверх^ к полной версии
DateTime params for RS reports (mostly rant) 12-01-2005 23:28


Непроверенные слухи об ExpressionHost, говорят, что он умнее, чем может показаться на первый взгляд. Хотите проверить?
Just inside "Label" box, select "Expression" and type something like :
=DateTime.Today.ToString()("mm/dd/yy").
комментарии: 0 понравилось! вверх^ к полной версии
Номинация года на тему 12-01-2005 14:11


Одно сочетание имен - Luis Felipe Cabrera, Don Box, Chistopher Kurt - в одной статье не может не остановить внимание. Это должно стать, как минимум, номинацией.
комментарии: 0 понравилось! вверх^ к полной версии
RS SP1 11-01-2005 16:57


Пропустил я совсем. Еще в июне(!) MS выпустила SP1 к Reporting Services. Удивительный образом, у меня он даже как-то уже сам собой успел установиться! К чему это я вспомнил? Установиться-то он установился, но вот документация к нему куда-то задевалась. Поэтому так бесполезно было искать в установленной у меня документации, что же такое rc:Parameters=False/True/Collapsed. Точно таким же образом, от меня скрылось, что в SP1 можно кастомизировать style sheet to the HTML Viewer. (rc:Stylesheet). Вот, кстати, и полный список того, что там наизменялось. В Израиле SP1 известен, прежде всего, тем, что в этом списке присутствует FIX 842536.
комментарии: 0 понравилось! вверх^ к полной версии
2 serialization engines for .NET Framework (not rant) 09-01-2005 16:05


Относительно XmlSerializer() и говорить-то особенно больше нечего. Он отлично будет (де)сериализовать ваши данные через XML, и, если вы еще разберетесь с атрибутами из System.Xml.Serialization, то можно будет сказать, что you are embraced the XML as data interchnage format. (Нельзя не заметить, что WebServices internally rely on the Xmlserializer to do object-to-SOAP transformations) Словом, MBV - marshal-by-value, в ваших руках. Ну, а что осталось для MBR?
Во-первых, понятно, что как бы ни сериализировать RPC-подобные вызовы для MBR, этим нельзя ограничиться. Кто-то должен эти вызовы передавать, принимать, направлять и т.д. и т.п. Добро пожаловать в .NET Remoting. Я хочу сказать, что SoapFormatter, BinaryFormatter and friends разрабатывались для .NET Remoting (о чем свидетельствует и то, что все они находятся в одном namespace - System.Runtime.Remoting) и без .NET Remoting понять их совершенно невозможно.
Теперь по сути. Начать с того, что SOAP specification определяет 4 разных типа документов, которыми занимается SOAP:
1). "document-style" message (section 5). Этот тип наиболее близок к XML-serialized messages. Сейчас мы заниматься им не будем.
2). Faults (section 4) - очень интересная и важная тема, особенно в контексте BizTalk. Но и этим типом мы займемся не сегодня.
3). Requests for method invocations and 4). their responses (section 7). Вот именно этим типом, который и решает вопросы MBR, мы и займемся сегодня. А еще точнее - его взаимодействием с .NET Remoting infrastructure.
Но, прежде всего, я хотел бы сказать пару слов о версиях SOAP. На сегодняшний день его рабочая версия - 1.1. Именно она поддеживается .NET Framework 1.0 и 1.1. Версия SOAP 1.2 пока является W3C Recommendation и, по всей видимости, будет поддеживаться .NET Framework 2.0. (Например, классы Soap12FaultCodes, SoapFaultSubcode). Пока я не собираюсь рассматривать версию 1.2.
комментарии: 0 понравилось! вверх^ к полной версии
Cw XmlSerializer 09-01-2005 02:03


Я позволю себе отложить до след. раза вопрос о том, зачем .NET Framework имеет 2 встроенных serialization engines. Один - из System.Xml.Serialization, другой - из System.Runtime.Serialization. Скажу сейчас только, что XmlSerializer работает со многими ограничениями security, и, что не менее важно, он занимается только сериализацией в XML. SoapFormatter() и BinaryFormatter() разработаны скорее больше для marshaling, и имеют дело с сетевой передачей сериализированных об'ектов, сохраняя также и object identity. Если этого мало, - ждите след. раза для более подробной дискуссии.
Сейчас я хотел сказать пару слов об XmlSerializer() и его возможностях обрабатывать choice particles из XSD. Во-первых, обращает на себя внимание аттрибут XmlChoiceIdentifierAttribute. Вот как им ,например, можно пользоваться :
[XmlType(Namespace="http://tempuri.org/finance.xsd",
IncludeInSchema=false)]
public enum CurrencyType
{
USDollars,
Euro,
}

[XmlType(Namespace="http://tempuri.org/finance.xsd")]
[XmlRoot("Payment", Namespace="http://tempuri.org/finance.xsd",
IsNullable=false)]
public class Payment
{
[XmlElement("USDollars", typeof(decimal))]
[XmlElement("Euro", typeof(decimal))]
[XmlChoiceIdentifier("Currency")]
public decimal amount;

[XmlIgnore()]
public CurrencyType Currency;
}
Здесь элементы USDollars и Euro соотвествуют очевидному choice particle, кот. привести здесь не могу из-за особенностей поддержки любых (в том числе и XML тэгов) в li.ru.
Вот не менее очевидный код код его сериализации:

StringWriter sw = new StringWriter();
Payment pt = new Payment();
pt.Currency = CurrencyType.USDollars;
pt.amount = 5.32M;
XmlSerializer ser2 = new XmlSerializer(typeof(Payment));
ser2.Serialize(sw, pt);
Console.Write(sw.ToString());

Этим примером я хотел сказать, что несмотря на то, что C# не поддержижает напрямую конструкций choice из XSD - выход все-таки есть.
Но Cw имеет встроенную поддержку для подобных конструкций. Продолжая начатый пример, перепишем то же на Cw
class CwPayment
{
struct
{
choice { decimal USDollars; decimal Euro; }
}
}
Вот и все. Но вот если пытаться серализировать этом класс с помощью XmlSerializer() - не получается. Он ориентирован на работу с аттрибутами из System.Xml. Никаких конструкций choice он не знает. ( как и всего Cw, собственно). Вот и пришлось разработчикам Cw писать свой XmlSerializer. Для желающих он доступен из Microsoft.Comega. Enjoy.
P.S. Не могу не привести и очень короткий пример сериализации из Cw:
pt = <cwpayment>
<euro>0.0</euro>
</cwpayment>;
decimal? initialAmount = pt.USDollars;
StringWriter sw = new StringWriter();

new Microsoft.Comega.XmlSerializer(typeof(CwPayment)).Serialize(sw, pt);
Console.WriteLine(sw.ToString());
комментарии: 0 понравилось! вверх^ к полной версии
UserControls, ServerControls & SPS. 26-12-2004 02:18


UserControls известны как ascx и, по сути, являются развитием идеи SSI - Server Side Includes. Они являются строительными блоками для ASP.NET 1, и еще это, конечно, code reuse. Они подключаются к WebPages с помощью директивы Register:
<%@ Register TagPrefix="OkeyUser" TagName="uc" Src="UserControl1.ascx" %>
В HTML части WebPage, такой UserControl выглядит примерно таким образом:
<form id="Form1" method="post" runat="server">
<OkeyUser:uc id="UC1" runat="server"></OkeyUser:uc>
</form>
комментарии: 0 понравилось! вверх^ к полной версии
Lutz Roeder's Reflector & Cw 25-12-2004 18:23


Такое впечатление, что никакого особенного шума Cw не поднял. Видимо, народ ждет C# 3.Тем временем, я решил добавить к его направлениям переписанного BTS, интеграцию с Reflector'ом. SDK Reflector'а можно найти здесь. Кроме того, сам по себе Reflector вставляется в MS Studio 2003. Попробуем...
This article will help
комментарии: 0 понравилось! вверх^ к полной версии
DPE - Data Processing Extension for RS 20-12-2004 00:52


Сам по себе DPE - это способ дать возможность сторонним призводителям поставлять свои DataSets в понимании RS. Имплементируем с десяток интерфейсов, упомянутых в Microsoft.ReportingServices.Interfaces и готово. Что получили? В конечном итоге получили имплементацию IDataReader, но не того, который из System.Data, a который из Microsoft.ReportingServices.DataProcessing! Обращаются с ними (к ним) очень даже похоже :


















System.Data ReportingServices.DataProcessing
DataTable GetSchemaTable() System.Type GetFieldType(int fieldIndex)
string GetName(int fieldIndex)
int GetOrdinal(string fieldName)
GetXXX() (из наследованного IDataRecord) GetValue(int fieldIndex)


RDL links to its DataSource via DataSources tag.
комментарии: 0 понравилось! вверх^ к полной версии
Зачем нужны subreports? (RS) 18-12-2004 20:08


Основное назначение subreports - связать dataregion более, чем с одним DataSet. Subreport принимает параметры, через которые и дается обычно эта связь.Например, таблица, вставленная в dataregion, связана с DataSet ds1, у кот. есть поле customerID. Допустим, сама таблица показывает заказы, сделанные этим customer. Его адрес и проч. данные, с другой стороны, допустим находятся в другом DataSet - ds2. Можно, конечно, переписать оба DataSet таким образом, чтобы каждый из них включал поле customerID и дальше сделать группировку по этому полю в исходной таблице. Но, во-первых, это может быть не так тривиально, и, что хуже того, исходные DataSets могут быть не доступны разработчику report. (Кстати, вот надо бы разобраться, почему нет "в комлекте RS" DPE - Data Processing Extension - для WebServices) Так вместо того, чтобы переписывать в меру возможности, DataSets, создается новый report с параметром customerID, в кот. показывается адрес и проч. Теперь осталось в одну из строчек исходной таблицы вставить subreport и откофигурировать его параметры. Получилось, что dataregion связан с двумя DataSets! Понятно, что у этого подхода есть performance drawback - серверы приходится обрабатывать два report'a. Поэтому, как правило, такой техники следует избегать, где можно - лучше иметь один DataSet.
комментарии: 0 понравилось! вверх^ к полной версии
Что я сам думаю о своем дневнике? Disclamer. 04-12-2004 02:11


Во-первых, этот дневник очень не последователен. Никому, кроме меня самого, найти здесь что-нибудь полезное не представляется возможным. Поэтому и не пытайтесь. Это личный дневник. Странно, что вообще, что у дневников на LI есть постоянные читатели. Типа развлекающиеся - анекдотиков им или фотки той, с кем вчера спал. Господа, мой дневник - ислючительно для меня. И дальше всех его подписчиков (т.наз. "друзей" или "постоянных читателей") я буду старательно вычищать. Я не ищу друзей или познакомиться с помощью этого дневника.
Во-вторых - сам я, лично, к своему дневнику имею претензии. Он задумывался, как профессиональный, так? Почему же здесь столько всего, не имеющего к software kibitzing никакого отношения? А с другой стороны, какой же software kibitzing в наше время, если нет даже упоминания ни о SOA, ни о EIF, ни о Indigo? Добавить! Причем в таком порядке - 1). EIF 2). SOA ( в плане BizTalk) 3). Indigo. И предварить все это введением в WMI.
комментарии: 0 понравилось! вверх^ к полной версии
Зачем мне хронометр? 19-11-2004 22:45


Я ношу часы swatch. Покупал я их в спешке, джанана настоящая, как в принципе и все остальное, что у меня было в семейной жизни. Даже не обратил внумание, покупая, что там нет календаря. Зато оказалось, что там есть хронометр. Первое время не знал даже, что мне мерять, хотя там как-то можно даже скорость машины измерять. Кстати, вот совершенно не понимаю, зачем за рулем кому-то может прийти в голову не смотреть на спидометр, а засекать скорость по ручному хронометру. Ну а уж не за рулем - так и подавно.
Но вот за последний месяц я нашел этому хронометру настоящее применение. Чем с тревогой смотреть в экран, в ожидании когда же призойдет deploy или еще с большей тревогой в ожидании первого забранного message, засечем время BTS performance на моем домашнем Dell с 250 Mb. Средний результат на лицо - этот пост сделан во время такого ожидания. ;)
комментарии: 0 понравилось! вверх^ к полной версии
Messages splitting in BTS2004 19-11-2004 18:13


Мне известно 3 способа произвести message splitting. Первый состоит в том, чтобы использовать custom pipeline с XMLDiassembler, кот. будет указывать на соответствующий envelope schema и document schema. Вот здесь можно найти подробные инструкции. Проблема с этим подходом, как замечает Darren Jefford, состоит уже хотя бы в том, что во-первых исходный message теряется, а он может содержать и другие атрибуты или элементы, а во-вторых, если, не нарушая schema, разумеется, один из элементов mailformed, весь pipeline завалится с exception.
Тут на помощь приходит xpath(). Эта функция встроена в XLANG/s и имеет очень большие возможности. Подробнее о них - см. здесь. Смысл идеи вот в чем : будем использовать xpath() чтобы получить кол-во искомых элементов. Например, так (внутри Expression Shape):

elementCount = xpath(inMsg, "count(/*[local-name()='store']/*[local-name()='Item'])");

Дальше используем Loop Shape, создавая на каждой итерации новый item message, опять же используя xpath():

XPathStatement = System.String.Format("/*[local-name()='store']/*[local-name()='Item'][{0}]",i);
itemMessage = xpath(inMsg,XPathStatement);
i = i + 1;

В обоих подходах в envelope schema (только при использовании xpath() ее не надо так объявлять), item message указывается, как reference.
Третий способ состоит в использовании Comega, и поэтому пока не разглашается. :)
комментарии: 0 понравилось! вверх^ к полной версии
Flat Files in BTS2004 06-11-2004 20:59


Никогда раньше не работал с Flat Files в BizTalk. Как говорится, бог миловал. Но вот нашелся FMR - ох, уж банков этих развелось. Шлют они (через FTP)такой вот flat :
0,26082004,26082004,00007203
1,26082004,26082004,00033081
2,26082004,26082004,00015627
3,26082004,26082004,00111798
5,26082004,26082004,00052383
4,26082004,26082004,00000006
Это как бы контрольный блок. Каждая строчка содержит номер другого файла (как например globs0, globs1, globs2 и т.д.), дату его создания, дату пересылки и кол-во строк в соответствующем файле.
Делаем так : для начала, всегда для flat files нужен pipeline с Flat Files Diasssambler. Он, собственно, и проделает всю работу по распоковке flat в XML. Только осталось придумать schema для такого flat.
BizTalk имеет несколько extensions для schemas. Я с ними имел дело, когда писал Ness Migrator. Но Migrator не регистрировался для editing, а из тех, которые зарегистрированы (EDI, FlatFiles, Hws) - надо выбрать, конечно,FlatFiles. Это добавит в schema properties кучу новых, из которых главные для нашего flat такие:
для определения общей структуры файла (под root) надо создать какой-нибудь child record и для него выбрать Child Delimiter - 0xD 0xA (перевод строки) и Child Delimiter Type - Hexadecimal.И в самом деле - все строчки в нашем flat закачиваются новой строкой.Очень важно и Child Order - в нашем случае - Postfix. Теперь определяем структуру для самих строк:
Child Delimiter - ,
Child Delimiter Type - Character
Child Order - Infix (Sic!)
Structure - Delimited (obviously)
Max Occurs - unbounded (*)
Min Occurs - 0 (?)
Вот и все. В самой schema не забудем выбрать: Standard - Flat File.
Disassmebler's Document schema должен указывать на только что построенную schema.
Для такого простого примера я даже не компилировал этот pipeline в отдельный assembly. Единственное неудобство при этом, что нельзя настроить Receive Location, не сделав предварительно deploy всего assembly.
Еще хочу обратить внимание - для Flat Files не требуется дополнительный splitting, как в случае с XML, который содержит schema envelope - Disassembler сам разобьет все строчки на отдельные элементы XML. И если сравнить, это совершенно правильно - оба они сплиттеры - и XML Disassembler, и FlatFile Disassembler, только один разбивает XML, а другой - flat. И в pipeline для них одно и тоже место - Disassemble stage.
комментарии: 0 понравилось! вверх^ к полной версии
Conditional filtering in T-SQL 23-10-2004 04:38


Вот пример, как обусловить горизонатльный фильтр (where clause) в SQL.

declare @bViewAll int
set @bViewAll = 1

create table #appr (time_id int)

if @bViewAll = 1
begin
insert into #appr
select top 100 time_id
from dbo.securitiesResults
end
else
insert into #appr
select top 100 time_id
from dbo.securitiesResults
where time_id = 250

select * from #appr

drop table #appr
комментарии: 0 понравилось! вверх^ к полной версии