tag:blogger.com,1999:blog-47511888834149193792024-02-07T00:29:42.683-05:00Philipp Munin - Tech LeadJavascript, Typescript, .NET, Full Stack, Team lead - New York City, NYPhilipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-4751188883414919379.post-1593014518514301062014-01-03T18:41:00.000-05:002018-05-18T16:46:32.425-04:00Data Access Tracing in .NET (Universal for any provider)Sometimes I'm surprised to see in .NET some very obvious, required functionality not available. I have to implement it by my own. When you develop database-driven web application you face a lot of issues and you need to diagnose if the issue is in database logic or on middle tier or on client. You can trace client and middle tier easily, but for some reason Microsoft thinks that you don't need the same with database access. Solution they provide to trace SQL requests are supercomplex and heavy (SQL Extended Events,...).<br />
<br />
So I had to spend couple of days to research and implement generic DbConnection tracing approach that supposed to work with any DbProvider. This approach should work with direct DbConnection as well as with ORM tools (EntityFramework). The idea is to replace standard DbProviderFactories with a wrappers, that will trace all necessary information. The Idea was taken from Glimpse.Ado.<br />
<br />
Here is the code:<br />
<script>githubFile("https://github.com/pmunin/pmunin.com/blob/master/posts/2014.05_Data_Access_Tracing_in_.NET/file1.cs")</script>
<br />
<pre style="background-color: white; font-family: Consolas; font-size: 13px;">And here is what you need to add to web.config:</pre>
<script>githubFile("https://github.com/pmunin/pmunin.com/blob/master/posts/2014.05_Data_Access_Tracing_in_.NET/web.config")</script>
<pre style="background-color: white; font-family: Consolas; font-size: 13px;"></pre>
<pre style="background-color: white; font-family: Consolas; font-size: 13px;"><pre style="background-position: initial initial; background-repeat: initial initial; font-family: Consolas;">
</pre>
<pre style="background-position: initial initial; background-repeat: initial initial; font-family: Consolas;">In application initialization module add line:</pre>
<pre style="background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"><pre style="font-family: Consolas;"><pre style="font-family: Consolas;"><span style="color: #2b91af;">TraceableDbProviderFactory.</span>IsEnabled = <span style="color: blue;">true</span><span style="color: #2b91af;">;</span></pre>
<pre style="font-family: Consolas;"></pre>
<pre style="font-family: Consolas;">Enjoy! </pre>
</pre>
</pre>
</pre>
Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-71485698049368615072013-10-16T13:57:00.005-04:002018-05-18T16:54:21.590-04:00Entity Framework Extensions to execute scalar queries (.First(), .Any(), .Count(), ...)If you have used LINQ to SQL, Entity Framework you might noticed that when you use queryable extensions returning set of objects (like .Select(), .Where(), .Join(), Group...) you get defered-executable queries that will be converted to SQL end executed during first demand. You can combine those queries, join them together, and it eventually will be still one SQL request. However you don't get the same when you work with functions returning not Enumerable, but actual value (like .First(), .Any(), .Max(), ...). So <a href="http://stackoverflow.com/questions/19385346" target="_blank">thanks to people from Stackoverflow</a>, here are extensions for DbContext and DbQuery (Entity Framework 5), that will allow you to execute those operations still getting back Queryable results:<br />
<script>githubFile("https://github.com/pmunin/pmunin.com/blob/master/posts/2013.10_Entity_Framework_Extensions_to_execute_scalar_queries/file1.cs")</script>
Here are examples, how to use this code:<br/>
<script>githubFile("https://github.com/pmunin/pmunin.com/blob/master/posts/2013.10_Entity_Framework_Extensions_to_execute_scalar_queries/file2.cs")</script>
SQL generated for each statement is the same:<br/>
<script>githubFile("https://github.com/pmunin/pmunin.com/blob/master/posts/2013.10_Entity_Framework_Extensions_to_execute_scalar_queries/file3.sql")</script>
Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-45985262567592829702013-09-26T20:12:00.000-04:002013-09-26T20:12:37.040-04:00T4 for generating composable functions for DbContext of Entity Framework 5 modelIf you try to Import Function which is composable using EF designer you will see error message :<br />
<b>Function imports cannot be created for composable functions</b>.<br />
<br />
However you can see that all data for those functions are imported to Storage space of the model. So there is enough information to generate functions wrappers automatically using T4 Template.<br />
The following T4 template is modified version of original EF5 Db Context T4 template - it only generates wrappers for composable functions code to your partial db context class. I didn't test it for different scenarios, so this is the raw version of T4 template:<br />
<br />
<br />
<pre style="background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><span style="background: yellow;"><#@</span> <span style="color: #a31515;">template</span> <span style="color: red;">language</span>=<span style="color: blue;">"C#"</span> <span style="color: red;">debug</span>=<span style="color: blue;">"false"</span> <span style="color: red;">hostspecific</span>=<span style="color: blue;">"true"</span><span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">include</span> <span style="color: red;">file</span>=<span style="color: blue;">"EF.Utility.CS.ttinclude"</span><span style="background: yellow;">#><#@</span>
<span style="color: #a31515;">output</span> <span style="color: red;">extension</span>=<span style="color: blue;">".cs"</span><span style="background: yellow;">#><#</span>
<span style="color: blue;">const</span> <span style="color: blue;">string</span> inputFile = <span style="color: #a31515;">@"Model1.edmx"</span>;
<span style="color: blue;">var</span> textTransformation = <span style="color: blue;">this</span>;
<span style="color: blue;">var</span> textTransform = DynamicTextTransformation.Create(textTransformation);
<span style="color: blue;">var</span> code = <span style="color: blue;">new</span> CodeGenerationTools(textTransformation);
<span style="color: blue;">var</span> ef = <span style="color: blue;">new</span> MetadataTools(textTransformation);
<span style="color: blue;">var</span> typeMapper = <span style="color: blue;">new</span> TypeMapper(code, ef, textTransform.Errors);
<span style="color: blue;">var</span> loader = <span style="color: blue;">new</span> EdmMetadataLoader(textTransform.Host, textTransform.Errors);
<span style="color: blue;">var</span> itemCollection = loader.CreateEdmItemCollection(inputFile);
<span style="color: blue;">var</span> modelNamespace = loader.GetModelNamespace(inputFile);
<span style="color: blue;">var</span> codeStringGenerator = <span style="color: blue;">new</span> CodeStringGenerator(code, typeMapper, ef);
<span style="color: blue;">var</span> container = itemCollection.OfType<EntityContainer>().FirstOrDefault();
<span style="color: blue;">var</span> mdl = <span style="color: blue;">new</span> MetadataLoader(textTransformation);
MetadataWorkspace ws = <span style="color: blue;">null</span>;
mdl.TryLoadAllMetadata(inputFile,<span style="color: blue;">out</span> ws);
<span style="color: blue;">var</span> storeItems = ws.GetItemCollection(DataSpace.SSpace);
<span style="color: blue;">var</span> functions = storeItems.OfType<EdmFunction>().Where(x=>x.NamespaceName!=<span style="color: #a31515;">"SqlServer"</span> && typeMapper.IsComposable(x)).ToArray();
<span style="background: yellow;">#></span>
<span style="color: green;">//------------------------------------------------------------------------------
// <auto-generated>
// </span><span style="background: yellow;"><#=</span>GetResourceString(<span style="color: #a31515;">"Template_GeneratedCodeCommentLine1"</span>)<span style="background: yellow;">#></span><span style="color: green;">
//
// </span><span style="background: yellow;"><#=</span>GetResourceString(<span style="color: #a31515;">"Template_GeneratedCodeCommentLine2"</span>)<span style="background: yellow;">#></span><span style="color: green;">
// </span><span style="background: yellow;"><#=</span>GetResourceString(<span style="color: #a31515;">"Template_GeneratedCodeCommentLine3"</span>)<span style="background: yellow;">#></span><span style="color: green;">
// </auto-generated>
//------------------------------------------------------------------------------
</span>
<span style="background: yellow;"><#</span>
<span style="color: blue;">var</span> codeNamespace = code.VsNamespaceSuggestion();
<span style="color: blue;">if</span> (!String.IsNullOrEmpty(codeNamespace))
{
<span style="background: yellow;">#></span>
<span style="color: blue;">namespace</span> <span style="background: yellow;"><#=</span>code.EscapeNamespace(codeNamespace)<span style="background: yellow;">#></span>
{
<span style="background: yellow;"><#</span>
PushIndent(<span style="color: #a31515;">" "</span>);
}
<span style="background: yellow;">#></span>
<span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> System.Data.Entity;
<span style="color: blue;">using</span> System.Data.Entity.Infrastructure;
<span style="color: blue;">using</span> System.Data.SqlClient;
<span style="background: yellow;"><#</span>
<span style="color: blue;">if</span> (container.FunctionImports.Any())
{
<span style="background: yellow;">#></span>
<span style="color: blue;">using</span> System.Data.Objects;
<span style="color: blue;">using</span> System.Data.Objects.DataClasses;
<span style="color: blue;">using</span> System.Linq;
<span style="background: yellow;"><#</span>
}
<span style="background: yellow;">#></span>
<span style="background: yellow;"><#=</span>Accessibility.ForType(container)<span style="background: yellow;">#></span> <span style="color: blue;">partial</span> <span style="color: blue;">class</span> <span style="background: yellow;"><#=</span>code.Escape(container)<span style="background: yellow;">#></span> : DbContext
{
<span style="background: yellow;"><#</span>
<span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> edmFunction <span style="color: blue;">in</span> functions)
{
WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: <span style="color: blue;">false</span>);
}
<span style="background: yellow;">#></span>
}
<span style="background: yellow;"><#</span>
<span style="color: blue;">if</span> (!String.IsNullOrEmpty(codeNamespace))
{
PopIndent();
<span style="background: yellow;">#></span>
}
<span style="background: yellow;"><#</span>
}
<span style="background: yellow;">#></span>
<span style="background: yellow;"><#+</span>
<span style="color: blue;">private</span> <span style="color: blue;">void</span> WriteFunctionImport(TypeMapper typeMapper, CodeStringGenerator codeStringGenerator, EdmFunction edmFunction, <span style="color: blue;">string</span> modelNamespace, <span style="color: blue;">bool</span> includeMergeOption)
{
<span style="background: yellow;">#></span>
[EdmFunction(<span style="color: #a31515;">"</span><span style="background: yellow;"><#=</span>edmFunction.NamespaceName<span style="background: yellow;">#></span><span style="color: #a31515;">"</span>, <span style="color: #a31515;">"</span><span style="background: yellow;"><#=</span>edmFunction.Name<span style="background: yellow;">#></span><span style="color: #a31515;">"</span>)]
<span style="background: yellow;"><#=</span>codeStringGenerator.ComposableStoreFunctionMethod(edmFunction, modelNamespace)<span style="background: yellow;">#></span>
{
<span style="background: yellow;"><#+</span>
codeStringGenerator.WriteStoreFunctionParameters(edmFunction, WriteFunctionParameter);
<span style="background: yellow;">#></span>
<span style="background: yellow;"><#=</span>codeStringGenerator.ComposableCreateStoreQuery(edmFunction, modelNamespace)<span style="background: yellow;">#></span>
}
<span style="background: yellow;"><#+</span>
}
<span style="color: blue;">public</span> <span style="color: blue;">void</span> WriteFunctionParameter(<span style="color: blue;">string</span> name, <span style="color: blue;">string</span> isNotNull, <span style="color: blue;">string</span> notNullInit, <span style="color: blue;">string</span> nullInit)
{
<span style="background: yellow;">#></span>
<span style="color: blue;">var</span> <span style="background: yellow;"><#=</span>name<span style="background: yellow;">#></span> = <span style="background: yellow;"><#=</span>isNotNull<span style="background: yellow;">#></span> ?
<span style="background: yellow;"><#=</span>notNullInit<span style="background: yellow;">#></span> :
<span style="background: yellow;"><#=</span>nullInit<span style="background: yellow;">#></span>;
<span style="background: yellow;"><#+</span>
}
<span style="color: blue;">public</span> <span style="color: blue;">const</span> <span style="color: blue;">string</span> TemplateId = <span style="color: #a31515;">"CSharp_DbContext_Context_EF5"</span>;
<span style="color: blue;">public</span> <span style="color: blue;">class</span> CodeStringGenerator
{
<span style="color: blue;">public</span> <span style="color: blue;">string</span> ComposableCreateStoreQuery(EdmFunction edmFunction, <span style="color: blue;">string</span> modelNamespace)
{
<span style="color: blue;">var</span> parameters = _typeMapper.GetParameters(edmFunction);
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"return ((IObjectContextAdapter)this).ObjectContext.ExecuteStoreQuery<{0}>(\"select [{1}].[{2}]({3})\"{4});"</span>,
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
<span style="color: green;">//edmFunction.NamespaceName,</span>
edmFunction.MetadataProperties[<span style="color: #a31515;">"Schema"</span>].Value,
edmFunction.Name,
<span style="color: blue;">string</span>.Join(<span style="color: #a31515;">", "</span>, parameters.Select(p => <span style="color: #a31515;">"@"</span> + p.EsqlParameterName).ToArray()),
_code.StringBefore(<span style="color: #a31515;">", "</span>, <span style="color: blue;">string</span>.Join(<span style="color: #a31515;">", "</span>, parameters.Select(p => p.ExecuteParameterName).ToArray())));
}
<span style="color: blue;">public</span> <span style="color: blue;">void</span> WriteStoreFunctionParameters(EdmFunction edmFunction, Action<<span style="color: blue;">string</span>, <span style="color: blue;">string</span>, <span style="color: blue;">string</span>, <span style="color: blue;">string</span>> writeParameter)
{
<span style="color: blue;">var</span> parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
<span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> parameter <span style="color: blue;">in</span> parameters.Where(p => p.NeedsLocalVariable))
{
<span style="color: blue;">var</span> isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + <span style="color: #a31515;">".HasValue"</span> : parameter.FunctionParameterName + <span style="color: #a31515;">" != null"</span>;
<span style="color: blue;">var</span> notNullInit = <span style="color: #a31515;">"new SqlParameter(\""</span> + parameter.EsqlParameterName + <span style="color: #a31515;">"\", "</span> + parameter.FunctionParameterName + <span style="color: #a31515;">")"</span>;
<span style="color: blue;">var</span> nullInit = <span style="color: #a31515;">"new SqlParameter(\""</span> + parameter.EsqlParameterName + <span style="color: #a31515;">"\", typeof("</span> + parameter.RawClrTypeName + <span style="color: #a31515;">"))"</span>;
writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
}
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> ComposableStoreFunctionMethod(EdmFunction edmFunction, <span style="color: blue;">string</span> modelNamespace)
{
<span style="color: blue;">var</span> parameters = _typeMapper.GetParameters(edmFunction);
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"{0} ObjectResult<{1}> {2}({3})"</span>,
AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
_code.Escape(edmFunction),
<span style="color: blue;">string</span>.Join(<span style="color: #a31515;">", "</span>, parameters.Select(p => p.FunctionParameterType + <span style="color: #a31515;">" "</span> + p.FunctionParameterName).ToArray()));
}
<span style="color: blue;">private</span> <span style="color: blue;">readonly</span> CodeGenerationTools _code;
<span style="color: blue;">private</span> <span style="color: blue;">readonly</span> TypeMapper _typeMapper;
<span style="color: blue;">private</span> <span style="color: blue;">readonly</span> MetadataTools _ef;
<span style="color: blue;">public</span> CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef)
{
ArgumentNotNull(code, <span style="color: #a31515;">"code"</span>);
ArgumentNotNull(typeMapper, <span style="color: #a31515;">"typeMapper"</span>);
ArgumentNotNull(ef, <span style="color: #a31515;">"ef"</span>);
_code = code;
_typeMapper = typeMapper;
_ef = ef;
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> Property(EdmProperty edmProperty)
{
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"{0} {1} {2} {{ {3}get; {4}set; }}"</span>,
Accessibility.ForProperty(edmProperty),
_typeMapper.GetTypeName(edmProperty.TypeUsage),
_code.Escape(edmProperty),
_code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
_code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> NavigationProperty(NavigationProperty navigationProperty)
{
<span style="color: blue;">var</span> endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"{0} {1} {2} {{ {3}get; {4}set; }}"</span>,
AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? (<span style="color: #a31515;">"ICollection<"</span> + endType + <span style="color: #a31515;">">"</span>) : endType,
_code.Escape(navigationProperty),
_code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
_code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> AccessibilityAndVirtual(<span style="color: blue;">string</span> accessibility)
{
<span style="color: blue;">return</span> accessibility + (accessibility != <span style="color: #a31515;">"private"</span> ? <span style="color: #a31515;">" virtual"</span> : <span style="color: #a31515;">""</span>);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> EntityClassOpening(EntityType entity)
{
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"{0} {1}partial class {2}{3}"</span>,
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(<span style="color: #a31515;">" : "</span>, _typeMapper.GetTypeName(entity.BaseType)));
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> EnumOpening(SimpleType enumType)
{
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"{0} enum {1} : {2}"</span>,
Accessibility.ForType(enumType),
_code.Escape(enumType),
_code.Escape(_typeMapper.UnderlyingClrType(enumType)));
}
<span style="color: blue;">public</span> <span style="color: blue;">void</span> WriteFunctionParameters(EdmFunction edmFunction, Action<<span style="color: blue;">string</span>, <span style="color: blue;">string</span>, <span style="color: blue;">string</span>, <span style="color: blue;">string</span>> writeParameter)
{
<span style="color: blue;">var</span> parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
<span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> parameter <span style="color: blue;">in</span> parameters.Where(p => p.NeedsLocalVariable))
{
<span style="color: blue;">var</span> isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + <span style="color: #a31515;">".HasValue"</span> : parameter.FunctionParameterName + <span style="color: #a31515;">" != null"</span>;
<span style="color: blue;">var</span> notNullInit = <span style="color: #a31515;">"new ObjectParameter(\""</span> + parameter.EsqlParameterName + <span style="color: #a31515;">"\", "</span> + parameter.FunctionParameterName + <span style="color: #a31515;">")"</span>;
<span style="color: blue;">var</span> nullInit = <span style="color: #a31515;">"new ObjectParameter(\""</span> + parameter.EsqlParameterName + <span style="color: #a31515;">"\", typeof("</span> + parameter.RawClrTypeName + <span style="color: #a31515;">"))"</span>;
writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
}
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> ComposableFunctionMethod(EdmFunction edmFunction, <span style="color: blue;">string</span> modelNamespace)
{
<span style="color: blue;">var</span> parameters = _typeMapper.GetParameters(edmFunction);
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"{0} IQueryable<{1}> {2}({3})"</span>,
AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
_code.Escape(edmFunction),
<span style="color: blue;">string</span>.Join(<span style="color: #a31515;">", "</span>, parameters.Select(p => p.FunctionParameterType + <span style="color: #a31515;">" "</span> + p.FunctionParameterName).ToArray()));
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> ComposableCreateQuery(EdmFunction edmFunction, <span style="color: blue;">string</span> modelNamespace)
{
<span style="color: blue;">var</span> parameters = _typeMapper.GetParameters(edmFunction);
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});"</span>,
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
edmFunction.NamespaceName,
edmFunction.Name,
<span style="color: blue;">string</span>.Join(<span style="color: #a31515;">", "</span>, parameters.Select(p => <span style="color: #a31515;">"@"</span> + p.EsqlParameterName).ToArray()),
_code.StringBefore(<span style="color: #a31515;">", "</span>, <span style="color: blue;">string</span>.Join(<span style="color: #a31515;">", "</span>, parameters.Select(p => p.ExecuteParameterName).ToArray())));
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> FunctionMethod(EdmFunction edmFunction, <span style="color: blue;">string</span> modelNamespace, <span style="color: blue;">bool</span> includeMergeOption)
{
<span style="color: blue;">var</span> parameters = _typeMapper.GetParameters(edmFunction);
<span style="color: blue;">var</span> returnType = _typeMapper.GetReturnType(edmFunction);
<span style="color: blue;">var</span> paramList = String.Join(<span style="color: #a31515;">", "</span>, parameters.Select(p => p.FunctionParameterType + <span style="color: #a31515;">" "</span> + p.FunctionParameterName).ToArray());
<span style="color: blue;">if</span> (includeMergeOption)
{
paramList = _code.StringAfter(paramList, <span style="color: #a31515;">", "</span>) + <span style="color: #a31515;">"MergeOption mergeOption"</span>;
}
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"{0} {1} {2}({3})"</span>,
AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
returnType == <span style="color: blue;">null</span> ? <span style="color: #a31515;">"int"</span> : <span style="color: #a31515;">"ObjectResult<"</span> + _typeMapper.GetTypeName(returnType, modelNamespace) + <span style="color: #a31515;">">"</span>,
_code.Escape(edmFunction),
paramList);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> ExecuteFunction(EdmFunction edmFunction, <span style="color: blue;">string</span> modelNamespace, <span style="color: blue;">bool</span> includeMergeOption)
{
<span style="color: blue;">var</span> parameters = _typeMapper.GetParameters(edmFunction);
<span style="color: blue;">var</span> returnType = _typeMapper.GetReturnType(edmFunction);
<span style="color: blue;">var</span> callParams = _code.StringBefore(<span style="color: #a31515;">", "</span>, String.Join(<span style="color: #a31515;">", "</span>, parameters.Select(p => p.ExecuteParameterName).ToArray()));
<span style="color: blue;">if</span> (includeMergeOption)
{
callParams = <span style="color: #a31515;">", mergeOption"</span> + callParams;
}
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});"</span>,
returnType == <span style="color: blue;">null</span> ? <span style="color: #a31515;">""</span> : <span style="color: #a31515;">"<"</span> + _typeMapper.GetTypeName(returnType, modelNamespace) + <span style="color: #a31515;">">"</span>,
edmFunction.Name,
callParams);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> DbSet(EntitySet entitySet)
{
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"{0} DbSet<{1}> {2} {{ get; set; }}"</span>,
Accessibility.ForReadOnlyProperty(entitySet),
_typeMapper.GetTypeName(entitySet.ElementType),
_code.Escape(entitySet));
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> UsingDirectives(<span style="color: blue;">bool</span> inHeader, <span style="color: blue;">bool</span> includeCollections = <span style="color: blue;">true</span>)
{
<span style="color: blue;">return</span> inHeader == <span style="color: blue;">string</span>.IsNullOrEmpty(_code.VsNamespaceSuggestion())
? <span style="color: blue;">string</span>.Format(
CultureInfo.InvariantCulture,
<span style="color: #a31515;">"{0}using System;{1}"</span> +
<span style="color: #a31515;">"{2}"</span>,
inHeader ? Environment.NewLine : <span style="color: #a31515;">""</span>,
includeCollections ? (Environment.NewLine + <span style="color: #a31515;">"using System.Collections.Generic;"</span>) : <span style="color: #a31515;">""</span>,
inHeader ? <span style="color: #a31515;">""</span> : Environment.NewLine)
: <span style="color: #a31515;">""</span>;
}
}
<span style="color: blue;">public</span> <span style="color: blue;">class</span> TypeMapper
{
<span style="color: blue;">private</span> <span style="color: blue;">const</span> <span style="color: blue;">string</span> ExternalTypeNameAttributeName = <span style="color: #a31515;">@"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName"</span>;
<span style="color: blue;">private</span> <span style="color: blue;">readonly</span> System.Collections.IList _errors;
<span style="color: blue;">private</span> <span style="color: blue;">readonly</span> CodeGenerationTools _code;
<span style="color: blue;">private</span> <span style="color: blue;">readonly</span> MetadataTools _ef;
<span style="color: blue;">public</span> TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors)
{
ArgumentNotNull(code, <span style="color: #a31515;">"code"</span>);
ArgumentNotNull(ef, <span style="color: #a31515;">"ef"</span>);
ArgumentNotNull(errors, <span style="color: #a31515;">"errors"</span>);
_code = code;
_ef = ef;
_errors = errors;
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetTypeName(TypeUsage typeUsage)
{
<span style="color: blue;">return</span> typeUsage == <span style="color: blue;">null</span> ? <span style="color: blue;">null</span> : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: <span style="color: blue;">null</span>);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetTypeName(EdmType edmType)
{
<span style="color: blue;">return</span> GetTypeName(edmType, isNullable: <span style="color: blue;">null</span>, modelNamespace: <span style="color: blue;">null</span>);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetTypeName(TypeUsage typeUsage, <span style="color: blue;">string</span> modelNamespace)
{
<span style="color: blue;">return</span> typeUsage == <span style="color: blue;">null</span> ? <span style="color: blue;">null</span> : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetTypeName(EdmType edmType, <span style="color: blue;">string</span> modelNamespace)
{
<span style="color: blue;">return</span> GetTypeName(edmType, isNullable: <span style="color: blue;">null</span>, modelNamespace: modelNamespace);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetTypeName(EdmType edmType, <span style="color: blue;">bool</span>? isNullable, <span style="color: blue;">string</span> modelNamespace)
{
<span style="color: blue;">if</span> (edmType == <span style="color: blue;">null</span>)
{
<span style="color: blue;">return</span> <span style="color: blue;">null</span>;
}
<span style="color: blue;">var</span> collectionType = edmType <span style="color: blue;">as</span> CollectionType;
<span style="color: blue;">if</span> (collectionType != <span style="color: blue;">null</span>)
{
<span style="color: blue;">return</span> String.Format(CultureInfo.InvariantCulture, <span style="color: #a31515;">"ICollection<{0}>"</span>, GetTypeName(collectionType.TypeUsage, modelNamespace));
}
<span style="color: blue;">var</span> typeName = _code.Escape(edmType.MetadataProperties
.Where(p => p.Name == ExternalTypeNameAttributeName)
.Select(p => (<span style="color: blue;">string</span>)p.Value)
.FirstOrDefault())
?? (modelNamespace != <span style="color: blue;">null</span> && edmType.NamespaceName != modelNamespace ?
_code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) :
_code.Escape(edmType));
<span style="color: blue;">if</span> (edmType <span style="color: blue;">is</span> StructuralType)
{
<span style="color: blue;">return</span> typeName;
}
<span style="color: blue;">if</span> (edmType <span style="color: blue;">is</span> SimpleType)
{
<span style="color: blue;">var</span> clrType = UnderlyingClrType(edmType);
<span style="color: blue;">if</span> (!IsEnumType(edmType))
{
typeName = _code.Escape(clrType);
}
<span style="color: blue;">return</span> clrType.IsValueType && isNullable == <span style="color: blue;">true</span> ?
String.Format(CultureInfo.InvariantCulture, <span style="color: #a31515;">"Nullable<{0}>"</span>, typeName) :
typeName;
}
<span style="color: blue;">throw</span> <span style="color: blue;">new</span> ArgumentException(<span style="color: #a31515;">"edmType"</span>);
}
<span style="color: blue;">public</span> Type UnderlyingClrType(EdmType edmType)
{
ArgumentNotNull(edmType, <span style="color: #a31515;">"edmType"</span>);
<span style="color: blue;">var</span> primitiveType = edmType <span style="color: blue;">as</span> PrimitiveType;
<span style="color: blue;">if</span> (primitiveType != <span style="color: blue;">null</span>)
{
<span style="color: blue;">return</span> primitiveType.ClrEquivalentType;
}
<span style="color: blue;">if</span> (IsEnumType(edmType))
{
<span style="color: blue;">return</span> GetEnumUnderlyingType(edmType).ClrEquivalentType;
}
<span style="color: blue;">return</span> <span style="color: blue;">typeof</span>(<span style="color: blue;">object</span>);
}
<span style="color: blue;">public</span> <span style="color: blue;">object</span> GetEnumMemberValue(MetadataItem enumMember)
{
ArgumentNotNull(enumMember, <span style="color: #a31515;">"enumMember"</span>);
<span style="color: blue;">var</span> valueProperty = enumMember.GetType().GetProperty(<span style="color: #a31515;">"Value"</span>);
<span style="color: blue;">return</span> valueProperty == <span style="color: blue;">null</span> ? <span style="color: blue;">null</span> : valueProperty.GetValue(enumMember, <span style="color: blue;">null</span>);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetEnumMemberName(MetadataItem enumMember)
{
ArgumentNotNull(enumMember, <span style="color: #a31515;">"enumMember"</span>);
<span style="color: blue;">var</span> nameProperty = enumMember.GetType().GetProperty(<span style="color: #a31515;">"Name"</span>);
<span style="color: blue;">return</span> nameProperty == <span style="color: blue;">null</span> ? <span style="color: blue;">null</span> : (<span style="color: blue;">string</span>)nameProperty.GetValue(enumMember, <span style="color: blue;">null</span>);
}
<span style="color: blue;">public</span> System.Collections.IEnumerable GetEnumMembers(EdmType enumType)
{
ArgumentNotNull(enumType, <span style="color: #a31515;">"enumType"</span>);
<span style="color: blue;">var</span> membersProperty = enumType.GetType().GetProperty(<span style="color: #a31515;">"Members"</span>);
<span style="color: blue;">return</span> membersProperty != <span style="color: blue;">null</span>
? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, <span style="color: blue;">null</span>)
: Enumerable.Empty<MetadataItem>();
}
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> EnumIsFlags(EdmType enumType)
{
ArgumentNotNull(enumType, <span style="color: #a31515;">"enumType"</span>);
<span style="color: blue;">var</span> isFlagsProperty = enumType.GetType().GetProperty(<span style="color: #a31515;">"IsFlags"</span>);
<span style="color: blue;">return</span> isFlagsProperty != <span style="color: blue;">null</span> && (<span style="color: blue;">bool</span>)isFlagsProperty.GetValue(enumType, <span style="color: blue;">null</span>);
}
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> IsEnumType(GlobalItem edmType)
{
ArgumentNotNull(edmType, <span style="color: #a31515;">"edmType"</span>);
<span style="color: blue;">return</span> edmType.GetType().Name == <span style="color: #a31515;">"EnumType"</span>;
}
<span style="color: blue;">public</span> PrimitiveType GetEnumUnderlyingType(EdmType enumType)
{
ArgumentNotNull(enumType, <span style="color: #a31515;">"enumType"</span>);
<span style="color: blue;">return</span> (PrimitiveType)enumType.GetType().GetProperty(<span style="color: #a31515;">"UnderlyingType"</span>).GetValue(enumType, <span style="color: blue;">null</span>);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> CreateLiteral(<span style="color: blue;">object</span> value)
{
<span style="color: blue;">if</span> (value == <span style="color: blue;">null</span> || value.GetType() != <span style="color: blue;">typeof</span>(TimeSpan))
{
<span style="color: blue;">return</span> _code.CreateLiteral(value);
}
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Format(CultureInfo.InvariantCulture, <span style="color: #a31515;">"new TimeSpan({0})"</span>, ((TimeSpan)value).Ticks);
}
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> VerifyCaseInsensitiveTypeUniqueness(IEnumerable<<span style="color: blue;">string</span>> types, <span style="color: blue;">string</span> sourceFile)
{
ArgumentNotNull(types, <span style="color: #a31515;">"types"</span>);
ArgumentNotNull(sourceFile, <span style="color: #a31515;">"sourceFile"</span>);
<span style="color: blue;">var</span> hash = <span style="color: blue;">new</span> HashSet<<span style="color: blue;">string</span>>(StringComparer.InvariantCultureIgnoreCase);
<span style="color: blue;">if</span> (types.Any(item => !hash.Add(item)))
{
_errors.Add(
<span style="color: blue;">new</span> CompilerError(sourceFile, -1, -1, <span style="color: #a31515;">"6023"</span>,
String.Format(CultureInfo.CurrentCulture, GetResourceString(<span style="color: #a31515;">"Template_CaseInsensitiveTypeConflict"</span>))));
<span style="color: blue;">return</span> <span style="color: blue;">false</span>;
}
<span style="color: blue;">return</span> <span style="color: blue;">true</span>;
}
<span style="color: blue;">public</span> IEnumerable<SimpleType> GetEnumItemsToGenerate(IEnumerable<GlobalItem> itemCollection)
{
<span style="color: blue;">return</span> GetItemsToGenerate<SimpleType>(itemCollection)
.Where(e => IsEnumType(e));
}
<span style="color: blue;">public</span> IEnumerable<T> GetItemsToGenerate<T>(IEnumerable<GlobalItem> itemCollection) <span style="color: blue;">where</span> T: EdmType
{
<span style="color: blue;">return</span> itemCollection
.OfType<T>()
.Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
.OrderBy(i => i.Name);
}
<span style="color: blue;">public</span> IEnumerable<<span style="color: blue;">string</span>> GetAllGlobalItems(IEnumerable<GlobalItem> itemCollection)
{
<span style="color: blue;">return</span> itemCollection
.Where(i => i <span style="color: blue;">is</span> EntityType || i <span style="color: blue;">is</span> ComplexType || i <span style="color: blue;">is</span> EntityContainer || IsEnumType(i))
.Select(g => GetGlobalItemName(g));
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetGlobalItemName(GlobalItem item)
{
<span style="color: blue;">if</span> (item <span style="color: blue;">is</span> EdmType)
{
<span style="color: blue;">return</span> ((EdmType)item).Name;
}
<span style="color: blue;">else</span>
{
<span style="color: blue;">return</span> ((EntityContainer)item).Name;
}
}
<span style="color: blue;">public</span> IEnumerable<EdmProperty> GetSimpleProperties(EntityType type)
{
<span style="color: blue;">return</span> type.Properties.Where(p => p.TypeUsage.EdmType <span style="color: blue;">is</span> SimpleType && p.DeclaringType == type);
}
<span style="color: blue;">public</span> IEnumerable<EdmProperty> GetSimpleProperties(ComplexType type)
{
<span style="color: blue;">return</span> type.Properties.Where(p => p.TypeUsage.EdmType <span style="color: blue;">is</span> SimpleType && p.DeclaringType == type);
}
<span style="color: blue;">public</span> IEnumerable<EdmProperty> GetComplexProperties(EntityType type)
{
<span style="color: blue;">return</span> type.Properties.Where(p => p.TypeUsage.EdmType <span style="color: blue;">is</span> ComplexType && p.DeclaringType == type);
}
<span style="color: blue;">public</span> IEnumerable<EdmProperty> GetComplexProperties(ComplexType type)
{
<span style="color: blue;">return</span> type.Properties.Where(p => p.TypeUsage.EdmType <span style="color: blue;">is</span> ComplexType && p.DeclaringType == type);
}
<span style="color: blue;">public</span> IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(EntityType type)
{
<span style="color: blue;">return</span> type.Properties.Where(p => p.TypeUsage.EdmType <span style="color: blue;">is</span> SimpleType && p.DeclaringType == type && p.DefaultValue != <span style="color: blue;">null</span>);
}
<span style="color: blue;">public</span> IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(ComplexType type)
{
<span style="color: blue;">return</span> type.Properties.Where(p => p.TypeUsage.EdmType <span style="color: blue;">is</span> SimpleType && p.DeclaringType == type && p.DefaultValue != <span style="color: blue;">null</span>);
}
<span style="color: blue;">public</span> IEnumerable<NavigationProperty> GetNavigationProperties(EntityType type)
{
<span style="color: blue;">return</span> type.NavigationProperties.Where(np => np.DeclaringType == type);
}
<span style="color: blue;">public</span> IEnumerable<NavigationProperty> GetCollectionNavigationProperties(EntityType type)
{
<span style="color: blue;">return</span> type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
}
<span style="color: blue;">public</span> FunctionParameter GetReturnParameter(EdmFunction edmFunction)
{
ArgumentNotNull(edmFunction, <span style="color: #a31515;">"edmFunction"</span>);
<span style="color: blue;">var</span> returnParamsProperty = edmFunction.GetType().GetProperty(<span style="color: #a31515;">"ReturnParameters"</span>);
<span style="color: blue;">return</span> returnParamsProperty == <span style="color: blue;">null</span>
? edmFunction.ReturnParameter
: ((IEnumerable<FunctionParameter>)returnParamsProperty.GetValue(edmFunction, <span style="color: blue;">null</span>)).FirstOrDefault();
}
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> IsComposable(EdmFunction edmFunction)
{
ArgumentNotNull(edmFunction, <span style="color: #a31515;">"edmFunction"</span>);
<span style="color: blue;">var</span> isComposableProperty = edmFunction.GetType().GetProperty(<span style="color: #a31515;">"IsComposableAttribute"</span>);
<span style="color: blue;">return</span> isComposableProperty != <span style="color: blue;">null</span> && (<span style="color: blue;">bool</span>)isComposableProperty.GetValue(edmFunction, <span style="color: blue;">null</span>);
}
<span style="color: blue;">public</span> IEnumerable<FunctionImportParameter> GetParameters(EdmFunction edmFunction)
{
<span style="color: blue;">return</span> FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
}
<span style="color: blue;">public</span> TypeUsage GetReturnType(EdmFunction edmFunction)
{
<span style="color: blue;">var</span> returnParam = GetReturnParameter(edmFunction);
<span style="color: blue;">return</span> returnParam == <span style="color: blue;">null</span> ? <span style="color: blue;">null</span> : _ef.GetElementType(returnParam.TypeUsage);
}
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> GenerateMergeOptionFunction(EdmFunction edmFunction, <span style="color: blue;">bool</span> includeMergeOption)
{
<span style="color: blue;">var</span> returnType = GetReturnType(edmFunction);
<span style="color: blue;">return</span> !includeMergeOption && returnType != <span style="color: blue;">null</span> && returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType;
}
}
<span style="color: blue;">public</span> <span style="color: blue;">class</span> EdmMetadataLoader
{
<span style="color: blue;">private</span> <span style="color: blue;">readonly</span> IDynamicHost _host;
<span style="color: blue;">private</span> <span style="color: blue;">readonly</span> System.Collections.IList _errors;
<span style="color: blue;">public</span> EdmMetadataLoader(IDynamicHost host, System.Collections.IList errors)
{
ArgumentNotNull(host, <span style="color: #a31515;">"host"</span>);
ArgumentNotNull(errors, <span style="color: #a31515;">"errors"</span>);
_host = host;
_errors = errors;
}
<span style="color: blue;">public</span> IEnumerable<GlobalItem> CreateEdmItemCollection(<span style="color: blue;">string</span> sourcePath)
{
ArgumentNotNull(sourcePath, <span style="color: #a31515;">"sourcePath"</span>);
<span style="color: blue;">if</span> (!ValidateInputPath(sourcePath))
{
<span style="color: blue;">return</span> <span style="color: blue;">new</span> EdmItemCollection();
}
<span style="color: blue;">var</span> schemaElement = LoadRootElement(_host.ResolvePath(sourcePath));
<span style="color: blue;">if</span> (schemaElement != <span style="color: blue;">null</span>)
{
<span style="color: blue;">using</span> (<span style="color: blue;">var</span> reader = schemaElement.CreateReader())
{
IList<EdmSchemaError> errors;
<span style="color: blue;">var</span> itemCollection = MetadataItemCollectionFactory.CreateEdmItemCollection(<span style="color: blue;">new</span>[] { reader }, <span style="color: blue;">out</span> errors);
ProcessErrors(errors, sourcePath);
<span style="color: blue;">return</span> itemCollection;
}
}
<span style="color: blue;">return</span> <span style="color: blue;">new</span> EdmItemCollection();
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetModelNamespace(<span style="color: blue;">string</span> sourcePath)
{
ArgumentNotNull(sourcePath, <span style="color: #a31515;">"sourcePath"</span>);
<span style="color: blue;">if</span> (!ValidateInputPath(sourcePath))
{
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Empty;
}
<span style="color: blue;">var</span> model = LoadRootElement(_host.ResolvePath(sourcePath));
<span style="color: blue;">if</span> (model == <span style="color: blue;">null</span>)
{
<span style="color: blue;">return</span> <span style="color: blue;">string</span>.Empty;
}
<span style="color: blue;">var</span> attribute = model.Attribute(<span style="color: #a31515;">"Namespace"</span>);
<span style="color: blue;">return</span> attribute != <span style="color: blue;">null</span> ? attribute.Value : <span style="color: #a31515;">""</span>;
}
<span style="color: blue;">private</span> <span style="color: blue;">bool</span> ValidateInputPath(<span style="color: blue;">string</span> sourcePath)
{
<span style="color: blue;">if</span> (sourcePath == <span style="color: #a31515;">"$"</span> + <span style="color: #a31515;">"edmxInputFile"</span> + <span style="color: #a31515;">"$"</span>)
{
_errors.Add(
<span style="color: blue;">new</span> CompilerError(_host.TemplateFile ?? sourcePath, 0, 0, <span style="color: blue;">string</span>.Empty,
GetResourceString(<span style="color: #a31515;">"Template_ReplaceVsItemTemplateToken"</span>)));
<span style="color: blue;">return</span> <span style="color: blue;">false</span>;
}
<span style="color: blue;">return</span> <span style="color: blue;">true</span>;
}
<span style="color: blue;">public</span> XElement LoadRootElement(<span style="color: blue;">string</span> sourcePath)
{
ArgumentNotNull(sourcePath, <span style="color: #a31515;">"sourcePath"</span>);
<span style="color: blue;">var</span> root = XElement.Load(sourcePath, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
<span style="color: blue;">return</span> root.Elements()
.Where(e => e.Name.LocalName == <span style="color: #a31515;">"Runtime"</span>)
.Elements()
.Where(e => e.Name.LocalName == <span style="color: #a31515;">"ConceptualModels"</span>)
.Elements()
.Where(e => e.Name.LocalName == <span style="color: #a31515;">"Schema"</span>)
.FirstOrDefault()
?? root;
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> ProcessErrors(IEnumerable<EdmSchemaError> errors, <span style="color: blue;">string</span> sourceFilePath)
{
<span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> error <span style="color: blue;">in</span> errors)
{
_errors.Add(
<span style="color: blue;">new</span> CompilerError(
error.SchemaLocation ?? sourceFilePath,
error.Line,
error.Column,
error.ErrorCode.ToString(CultureInfo.InvariantCulture),
error.Message)
{
IsWarning = error.Severity == EdmSchemaErrorSeverity.Warning
});
}
}
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> IsLazyLoadingEnabled(EntityContainer container)
{
<span style="color: blue;">string</span> lazyLoadingAttributeValue;
<span style="color: blue;">var</span> lazyLoadingAttributeName = MetadataConstants.EDM_ANNOTATION_09_02 + <span style="color: #a31515;">":LazyLoadingEnabled"</span>;
<span style="color: blue;">bool</span> isLazyLoading;
<span style="color: blue;">return</span> !MetadataTools.TryGetStringMetadataPropertySetting(container, lazyLoadingAttributeName, <span style="color: blue;">out</span> lazyLoadingAttributeValue)
|| !<span style="color: blue;">bool</span>.TryParse(lazyLoadingAttributeValue, <span style="color: blue;">out</span> isLazyLoading)
|| isLazyLoading;
}
}
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> ArgumentNotNull<T>(T arg, <span style="color: blue;">string</span> name) <span style="color: blue;">where</span> T : <span style="color: blue;">class</span>
{
<span style="color: blue;">if</span> (arg == <span style="color: blue;">null</span>)
{
<span style="color: blue;">throw</span> <span style="color: blue;">new</span> ArgumentNullException(name);
}
}
<span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">readonly</span> Lazy<System.Resources.ResourceManager> ResourceManager =
<span style="color: blue;">new</span> Lazy<System.Resources.ResourceManager>(
() => <span style="color: blue;">new</span> System.Resources.ResourceManager(<span style="color: #a31515;">"System.Data.Entity.Design"</span>, <span style="color: blue;">typeof</span>(MetadataItemCollectionFactory).Assembly), isThreadSafe: <span style="color: blue;">true</span>);
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">string</span> GetResourceString(<span style="color: blue;">string</span> resourceName)
{
ArgumentNotNull(resourceName, <span style="color: #a31515;">"resourceName"</span>);
<span style="color: blue;">return</span> ResourceManager.Value.GetString(resourceName, <span style="color: blue;">null</span>);
}
<span style="background: yellow;">#></span></pre>
Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-9615161411843848872013-09-26T15:30:00.002-04:002013-09-26T15:30:45.553-04:00Entity Framework Function Import does not work with SP which use temp tables in itIf you ever tried to generate Entity Framework model from database for Stored Procedures (Function Import) - you might have notices that Entity Framework cannot receive information about columns for those SP which uses temp tables in it.<br />
<br />
The Reason for that is that EF importer tries to execute that SP with FMTONLY set to ON, which makes you SP fail, as temp tables are not created when FMTONLY=ON.<br />
<br />
In order to make those SP work, you can make the following changes:<br />
1) Add to the beginning of the SP code:<br />
<span style="color: blue; font-family: Consolas; font-size: 13px;">DECLARE</span><span style="background-color: white; font-family: Consolas; font-size: 13px;"> </span><span style="color: teal; font-family: Consolas; font-size: 13px;">@FMTONLY</span><span style="background-color: white; font-family: Consolas; font-size: 13px;"> </span><span style="color: blue; font-family: Consolas; font-size: 13px;">BIT</span><span style="color: grey; font-family: Consolas; font-size: 13px;">;</span><br />
<pre style="background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><span style="color: blue;">if</span> 1<span style="color: grey;">=</span>0
<span style="color: blue;">BEGIN</span>
<span style="color: blue;">set</span> <span style="color: teal;">@FMTONLY</span> <span style="color: grey;">=</span> 1<span style="color: grey;">;</span>
<span style="color: blue;">SET</span> <span style="color: blue;">FMTONLY</span> <span style="color: blue;">OFF</span><span style="color: grey;">;</span>
<span style="color: blue;">END</span>
</pre>
<div>
<br /></div>
<div>
2) Add to the end of SP:</div>
<div>
<pre style="background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><span style="color: blue;">if</span> <span style="color: teal;">@FMTONLY</span> <span style="color: grey;">=</span> 1
<span style="color: blue;">BEGIN</span>
<span style="color: blue;">SET</span> <span style="color: blue;">FMTONLY</span> <span style="color: blue;">ON</span><span style="color: grey;">;</span>
<span style="color: blue;">END</span></pre>
</div>
<div>
<br /></div>
<div>
This will fix your issue with Function Import caused by using temp tables. If you keep seeing that Entity Framework does not receive information about columns, probably the problem is in something else, you can figure it out trying to execute your store proc with FMTONLY ON, like that:</div>
<div>
<br /></div>
<div>
<pre style="background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><span style="color: blue;">SET</span> <span style="color: blue;">FMTONLY</span> <span style="color: blue;">ON</span><span style="color: grey;">;</span>
<span style="color: blue;">exec</span> <span style="color: teal;">MyProcedureThatDoesNotReturnsColumnsToEF</span></pre>
</div>
Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-38623568264330927652013-09-24T18:58:00.000-04:002013-09-24T19:02:59.186-04:00T4 Template for Visual Studio Settings fileLet's say you have .NET application with settings. Visual Studio does a great job generating class with properties that allows to access those settings, and let's say if you renamed the Setting name you will find out all reference errors during compile time, which is great.<br />
<br />
However sometimes you might need to get names of Settings properties as constants - you might need it for using those settings in Attribute initializers, which allow only constant parameters.<br />
<br />
So here is T4 template that generates subclass with names as constants and names as Enumerable (for strongly typed references):<br />
<br />
<pre style="background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><pre style="background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"><pre style="background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"><pre style="background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"><span style="background: yellow;"><#@</span> <span style="color: #a31515;">template</span> <span style="color: red;">language</span>=<span style="color: blue;">"C#"</span> <span style="color: red;">debug</span>=<span style="color: blue;">"true"</span> <span style="color: red;">hostSpecific</span>=<span style="color: blue;">"true"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">output</span> <span style="color: red;">extension</span>=<span style="color: blue;">".cs"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">Assembly</span> <span style="color: red;">Name</span>=<span style="color: blue;">"System.Core.dll"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">Assembly</span> <span style="color: red;">Name</span>=<span style="color: blue;">"System.Xml.dll"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">Assembly</span> <span style="color: red;">Name</span>=<span style="color: blue;">"System.Xml.Linq.dll"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">Assembly</span> <span style="color: red;">Name</span>=<span style="color: blue;">"System.Windows.Forms.dll"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">Assembly</span> <span style="color: red;">name</span>=<span style="color: blue;">"System.Configuration"</span><span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">assembly</span> <span style="color: red;">name</span>=<span style="color: blue;">"EnvDTE"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"System"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"System.IO"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"System.Diagnostics"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"System.Linq"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"System.Xml.Linq"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"System.Collections"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"System.Collections.Specialized"</span><span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"System.Collections.Generic"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"System.Configuration"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#@</span> <span style="color: #a31515;">import</span> <span style="color: red;">namespace</span>=<span style="color: blue;">"Microsoft.VisualStudio.TextTemplating"</span> <span style="background: yellow;">#></span>
<span style="background: yellow;"><#</span>
<span style="color: blue;">const</span> <span style="color: blue;">string</span> SettingsFile = <span style="color: #a31515;">"Settings.settings"</span>;
<span style="background: yellow;">#></span>
<span style="color: green;">/*
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a template.
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
*/</span>
<span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> System.Configuration;
<span style="background: yellow;"><#</span>
<span style="color: blue;">var</span> doc = XDocument.Load(Path.Combine(<span style="color: blue;">this</span>.GetTemplatePath(), SettingsFile));
<span style="color: blue;">var</span> xmlNs = doc.Root.Name.Namespace;
<span style="background: yellow;">#></span>
<span style="color: blue;">namespace</span> <span style="background: yellow;"><#=</span> doc.Root.Attribute(<span style="color: #a31515;">"GeneratedClassNamespace"</span>).Value <span style="background: yellow;">#></span>
{
<span style="color: blue;">partial</span> <span style="color: blue;">class</span> <span style="background: yellow;"><#=</span> doc.Root.Attribute(<span style="color: #a31515;">"GeneratedClassName"</span>).Value <span style="background: yellow;">#></span>
{
<span style="color: green;">/// <summary>
/// Contains all settings' names
/// </summary>
</span> <span style="color: blue;">public</span> <span style="color: blue;">class</span> Names
{
<span style="background: yellow;"><#</span> <span style="color: blue;">foreach</span>(<span style="color: blue;">var</span> setting <span style="color: blue;">in</span> doc.Descendants(xmlNs+<span style="color: #a31515;">"Setting"</span>)) {
<span style="color: blue;">var</span> settingName = setting.Attribute(<span style="color: #a31515;">"Name"</span>).Value;
<span style="background: yellow;">#></span>
<span style="background: yellow;"><#</span>
<span style="color: blue;">var</span> settingDescription = setting.Attribute(<span style="color: #a31515;">"Description"</span>)==<span style="color: blue;">null</span>?<span style="color: blue;">null</span>:setting.Attribute(<span style="color: #a31515;">"Description"</span>).Value;
<span style="color: blue;">if</span>(!<span style="color: blue;">string</span>.IsNullOrEmpty(settingDescription))
{
<span style="background: yellow;">#></span>
<span style="color: green;">/// <summary>
/// </span><span style="background: yellow;"><#=</span> settingDescription <span style="background: yellow;">#></span><span style="color: green;">
/// </summary>
</span> <span style="background: yellow;"><#</span> } <span style="background: yellow;">#></span>
<span style="color: blue;">public</span> <span style="color: blue;">const</span> <span style="color: blue;">string</span> <span style="background: yellow;"><#=</span> GetSafeName(settingName) <span style="background: yellow;">#></span> = <span style="color: #a31515;">"</span><span style="background: yellow;"><#=</span> settingName <span style="background: yellow;">#></span><span style="color: #a31515;">"</span>;
<span style="background: yellow;"><#</span> } <span style="background: yellow;">#></span>
}
<span style="color: green;">/// <summary>
/// Contains enumeration of all settings, you can use it as strong type key for specific setting
/// </summary>
</span> <span style="color: blue;">public</span> <span style="color: blue;">enum</span> NameEnum
{
<span style="background: yellow;"><#</span> <span style="color: blue;">foreach</span>(<span style="color: blue;">var</span> setting <span style="color: blue;">in</span> doc.Descendants(xmlNs+<span style="color: #a31515;">"Setting"</span>)) {
<span style="color: blue;">var</span> settingName = setting.Attribute(<span style="color: #a31515;">"Name"</span>).Value;<span style="background: yellow;">#></span>
<span style="background: yellow;"><#</span>
<span style="color: blue;">var</span> settingDescription = setting.Attribute(<span style="color: #a31515;">"Description"</span>)==<span style="color: blue;">null</span>?<span style="color: blue;">null</span>:setting.Attribute(<span style="color: #a31515;">"Description"</span>).Value;
<span style="color: blue;">if</span>(!<span style="color: blue;">string</span>.IsNullOrEmpty(settingDescription))
{
<span style="background: yellow;">#></span>
<span style="color: green;">/// <summary>
/// </span><span style="background: yellow;"><#=</span> settingDescription <span style="background: yellow;">#></span><span style="color: green;">
/// </summary>
</span> <span style="background: yellow;"><#</span> } <span style="background: yellow;">#></span>
<span style="background: yellow;"><#=</span> GetSafeName(settingName) <span style="background: yellow;">#></span>,
<span style="background: yellow;"><#</span> } <span style="background: yellow;">#></span>
}
<span style="color: green;">/// <summary>
/// Gives setting value by name passed as enum
/// </summary>
/// <param name="settingName">setting key</param>
/// <returns>setting value</returns>
</span> <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">object</span> GetValue(NameEnum settingName)
{
<span style="color: blue;">return</span> Default[settingName.ToString()];
}
<span style="color: green;">/// <summary>
/// Gives specified type setting value by name passed as enum
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="settingName"></param>
/// <returns>setting calue of specified type</returns>
</span> <span style="color: blue;">public</span> <span style="color: blue;">static</span> T GetValue<T>(NameEnum settingName)
{
<span style="color: blue;">return</span> (T)Default[settingName.ToString()];
}
}
}
<span style="background: yellow;"><#+</span>
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetTemplatePath ( )
{
<span style="color: blue;">return</span> Path.GetDirectoryName(Host.TemplateFile);
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> GetSafeName ( <span style="color: blue;">string</span> value)
{
<span style="color: blue;">var</span> builder = <span style="color: blue;">new</span> System.Text.StringBuilder();
<span style="color: blue;">foreach</span>(<span style="color: blue;">var</span> ch <span style="color: blue;">in</span> value)
{
<span style="color: blue;">if</span> (Char.IsLetterOrDigit(ch) || ch == <span style="color: #a31515;">'_'</span>)
builder.Append(ch);
<span style="color: blue;">else</span> <span style="color: blue;">if</span> (ch == <span style="color: #a31515;">'.'</span>)
builder.Append(<span style="color: #a31515;">'_'</span>);
};
<span style="color: blue;">return</span> builder.ToString();
}
<span style="background: yellow;">#></span>
</pre>
</pre>
</pre>
</pre>
<div>
<br /></div>
<div>
<br /><t>
</t><br />
You will can use this template for other settings files in your application, in order to do that just change SettingsFile constant.</div>
Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-12941341421058426242013-04-18T06:30:00.003-04:002023-03-02T09:50:20.660-05:00Dynamically generated Javascript and CSS in ASP.NET MVC using Razor ViewsI was always wondering why ASP.NET allows to generate dynamically HTML (including inline CSS and JS), but does not allow to do the same for standalone JS and CSS files. Today I spent some time to implement relatively simple and convenient solution of the problem on ASP.NET MVC platform.<br />
<br />
Here is the <u>list of features</u> I want to get from solution:<br />
<ul>
<li>Intelli-sense in editor of dynamic CSS and JS </li>
<li>Fully functional C# razor with server-side C# code in dynamic content </li>
<li>Ability to pass Model and use request parameters </li>
<li>I still want to use some static CSS, and JS besides dynamic </li>
<li>Adding another dynamic JS/CSS file should be as easy as adding static JS/CSS file</li>
</ul>
Here is what <u>OUT OF SCOPE</u>:<br />
<ul>
<li>Bundling and minification of resources</li>
</ul>
<h3>
Short story</h3>
To achieve these goals, I use existing functionality of CSHTML editor, which provides everything we need for inline CSS and JS. I create partial cshtml view with single Html element, either or and after rendering I trim the root tag and get dynamically rendered content file.<br />
The steps you will need to do:<br />
1) Implement CSHTML files to render dynamic resources<br />
2) Implement Style and Script controllers, overriding handling unknown action, using "Magic" extensions<br />
3) Modify web.config to allow controllers handle static file requests<br />
4) Implement Magic extensions.<br />
5) Enjoy<br />
<br />
<i><span style="font-size: large;"><a href="https://drive.google.com/file/d/0Bxp4SNNLrAEEVmNkekZ5cV82ZDA/view?usp=share_link&resourcekey=0-OcsdrSJHTu08CoH6_hYtNw"><b>Here</b></a> you can download source code</span>.</i><br />
<br />
<br />
<h3>
Long story:</h3>
<h4>
</h4>
<h4>
CREATING TARGET VIEW</h4>
Let's start with our final view, which declares our implementation goals. It is super simple home page view, that references our dynamic and static content, and demonstrate visually that using of dynamic resources works:<br />
<b>Index.cshtml:</b><br />
<br />
<span style="background-color: yellow;">@{</span><br />
<pre style="background-color: white; font-family: consolas; font-size: 13px;"> ViewBag.Title = <span style="color: #a31515;">"Home page"</span>;
<span style="background: yellow;">}</span>
<span style="color: blue;"><</span><span style="color: maroon;">link</span> <span style="color: red;">href</span><span style="color: blue;">=</span><span style="color: blue;">"~/Styles/<b>static.css</b>"</span> <span style="color: red;">rel</span><span style="color: blue;">=</span><span style="color: blue;">"stylesheet"</span> <span style="color: blue;">/></span>
<span style="color: blue;"><</span><span style="color: maroon;">link</span> <span style="color: red;">href</span><span style="color: blue;">=</span><span style="color: blue;">"~/Styles/<b>dynamic.css</b>?color=grey"</span> <span style="color: red;">rel</span><span style="color: blue;">=</span><span style="color: blue;">"stylesheet"</span> <span style="color: blue;">/></span>
<span style="color: blue;"><</span><span style="color: maroon;">script</span> <span style="color: red;">src</span><span style="color: blue;">=</span><span style="color: blue;">"~/Scripts/<b>static.js</b>"</span><span style="color: blue;">></</span><span style="color: maroon;">script</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: maroon;">script</span> <span style="color: red;">src</span><span style="color: blue;">=</span><span style="color: blue;">"~/Scripts/<b>dynamicWithModel.js</b>?message=Hallo%20world&otherParameter=My parameter value"</span><span style="color: blue;">></</span><span style="color: maroon;">script</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: maroon;">script</span> <span style="color: red;">src</span><span style="color: blue;">=</span><span style="color: blue;">"~/Scripts/<b>otherDynamic.js</b>"</span><span style="color: blue;">></</span><span style="color: maroon;">script</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: maroon;">h2</span> <span style="color: red;">class</span><span style="color: blue;">=</span><span style="color: blue;">"dynamicCss"</span><span style="color: blue;">></span><span style="background: yellow;">@</span>ViewBag.Title<span style="color: blue;"></</span><span style="color: maroon;">h2</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: maroon;">script</span><span style="color: blue;">></span>
StaticJsFunction();
DynamicJsFunction();
OtherDynamicJsFunction();
<span style="color: blue;"></</span><span style="color: maroon;">script</span><span style="color: blue;">></span></pre>
<br />
You can see that this view uses dynamic CSS and static CSS. It also uses one static JS file, and two dynamic JS files. Dynamic references has query string parameters which will impact the rendering of the resource. In DynamicWithModel.js I also wants to use model that I pass to the JS-view and which is respected during JS rendering.<br />
<br />
I want my dynamic resources to be handler by controllers, while static resources should be stored just in Styles and Scripts folder of the web application.<br />
<br />
<br />
<h3>
Creating JS and CSS</h3>
<br />
For static resources I create folders in the root of the project. Regarding dynamic resources, since controllers should be named Styles and Scripts, I will create view folders accordingly with CSHTML files:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQIt_sD1sX_0YzHpW8kmXfyifoFAKKGSmjOLp5ZcGuvLtWeHSPgD99-dPRotntVstf-WAV265CSylbktf9_45sGTaPgpyEHWuDtDl81vqSppPUAHPzMMY24XoxOElJSbeDQcrEaYOLSST4/s1600-h/image%25255B4%25255D.png"><img alt="image" border="0" height="508" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZLbk7FkBTKt5WTWEeaHyxFEeKlswzuH81KQnO-GTqTL1zoaDl_EPfSaOog0RezMLzCtcNrV1Uoa_FzOShFxQYF4XtdcRGXkBTkG6uD2L_blbp_MjmyEJxunDSf-dwU4R_Ct2G0pxqQgLp/?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="362" /></a><br />
<br />
Content of those static files is very simple:<br />
<b>~/scripts/static.js:</b><br />
<br />
<pre style="background-color: white; font-family: consolas; font-size: 13px;"><span style="color: blue;">function</span> StaticJsFunction() {
document.writeln(<span style="color: #a31515;">"executing static JS
"</span>);
}</pre>
<br />
<br />
<b>~/scripts/static.css:</b><br />
<br />
<pre style="background-color: white; font-family: consolas; font-size: 13px;"><span style="color: maroon;">body</span> {
<span style="color: red;">background-color</span>:<span style="color: blue;">InfoBackground</span>;
}</pre>
<br />
<br />
Here are dynamic resources:<br />
<b>~/Views/Styles/dynamic.css.cshtml:</b><br />
<br />
<br />
<blockquote class="tr_bq">
<span style="background: yellow;">@{</span> <span style="color: blue;">var</span> className = <span style="color: #a31515;">"dynamicCss"</span>;<br />
<span style="color: blue;">var</span> bkColor = Request.QueryString[<span style="color: #a31515;">"color"</span>]??<span style="color: #a31515;">"red"</span>;<br />
<span style="background: yellow;">}</span><span style="color: blue;"><</span><span style="color: maroon;">style</span><span style="color: blue;">></span>.<span style="background: yellow;">@</span>className<br />
{<br />
background-color:<span style="background: yellow;">@</span>bkColor;<br />
}<br />
<span style="color: blue;"></</span><span style="color: maroon;">style</span><span style="color: blue;">></span></blockquote>
<br />
As you see CSHTML is standard view with a single block STYLE node. Background color is retrieved <b>from query string parameter</b>, in case parameter is not specified default RED color is used.<br />
<br />
<b>~/Views/Scripts/DynamicWithModel.js.cshtml:</b><br />
<br />
<br />
<div class="tr_bq">
<span style="background: yellow;">@model </span><span style="color: blue;">string</span><span style="color: blue;"><</span><span style="color: maroon;">script</span><span style="color: blue;">></span><span style="color: blue;">function</span> DynamicJsFunction() {<br />
document.writeln(<span style="color: #a31515;">"executing dynamic JS from: </span><span style="background: yellow;">@</span>Request.RawUrl<span style="color: #a31515;">...</span>")<br />
<span style="background: yellow;">@</span><span style="color: blue;">if</span> (Model != <span style="color: blue;">null</span>)<br />
{<br />
<span style="background: yellow;">@:</span> { document.writeln(<span style="color: #a31515;">"Message passed to Model: </span><span style="background: yellow;">@</span>Model<span style="color: #a31515;"></span>"); }<br />
}<br />
<span style="background: yellow;">@</span><span style="color: blue;">if</span> (Request.QueryString.HasKeys())<br />
{<br />
<span style="color: blue;">foreach</span> (<span style="color: blue;">string</span> key <span style="color: blue;">in</span> Request.QueryString.Keys)<br />
{<br />
<span style="background: yellow;">@:</span>{ document.writeln(<span style="color: #a31515;">"Query string parameter. Key: </span><span style="background: yellow;">@</span>key<span style="color: #a31515;"> , Value: </span><span style="background: yellow;">@</span>Request.QueryString[key]<span style="color: #a31515;"></span>"); }<br />
}<br />
}<br />
}<br />
<span style="color: blue;"></</span><span style="color: maroon;">script</span><span style="color: blue;">></span></div>
<br />
<div class="tr_bq">
<br /></div>
<br />
<div class="tr_bq">
<span style="color: blue;"></span>As you see this JS is a function renders to current document model and query string parameters which were specified during rendering the JS content.<br />
<br />
<b>~/Views/Scripts/OtherDynamic.js.cshtml:</b></div>
<br />
<div class="tr_bq">
<span style="color: blue;"><</span><span style="color: maroon;">script</span><span style="color: blue;">></span> <span style="color: blue;">function</span> OtherDynamicJsFunction() {<br />
document.writeln(<span style="color: #a31515;">"executing Other dynamic JS from: </span><span style="background: yellow;">@</span>Request.RawUrl<span style="color: #a31515;">...</span></div>
")<br />
<span style="background: yellow;">@</span><span style="color: blue;">if</span> (Request.QueryString.HasKeys())<br />
{<br />
<span style="color: blue;">foreach</span> (<span style="color: blue;">string</span> key <span style="color: blue;">in</span> Request.QueryString.Keys)<br />
{<br />
<span style="background: yellow;">@:</span>{ document.writeln(<span style="color: #a31515;">"Query string parameter. Key: </span><span style="background: yellow;">@</span>key<span style="color: #a31515;"> , Value: </span><span style="background: yellow;">@</span>Request.QueryString[key]<span style="color: #a31515;"></span>"); }<br />
}<br />
}<br />
}<br />
<span style="color: blue;"></</span><span style="color: maroon;">script</span><span style="color: blue;">></span><br />
This function does not use model, but also renders current query string parameters to Html document.<br />
<br />
<br />
<br />
<h3>
Creating Scripts and Styles Controllers</h3>
<br />
I’m creating two controllers which handles requests coming to ~/Styles/* and ~/Scripts/* paths.<br />
<br />
<br />
<pre style="background-color: white; font-family: consolas; font-size: 13px;"> <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">StylesController</span> : <span style="color: #2b91af;">Controller</span>
{
<span style="color: blue;">public</span> <span style="color: #2b91af;">ActionResult</span> Index()
{
<span style="color: blue;">return</span> Content(<span style="color: #a31515;">"Styles folder"</span>);
}
<span style="color: blue;">protected</span> <span style="color: blue;">override</span> <span style="color: blue;">void</span> HandleUnknownAction(<span style="color: blue;">string</span> actionName)
{
<span style="color: blue;">var</span> res = <span style="color: blue;">this</span>.<b>CssFromView</b>(actionName);
res.ExecuteResult(ControllerContext);
}
}</pre>
<pre style="background-color: white; font-family: consolas; font-size: 13px;"></pre>
<pre style="background-color: white; font-family: consolas; font-size: 13px;"><pre style="font-family: consolas;">Since I don't want to register action for every single CSS and JS file, I override <b>HandleUnknownAction</b> to handle all requests to controller that were not associated with declared action.</pre>
<div>
</div>
</pre>
<pre style="background-color: white; font-family: consolas; font-size: 13px;"></pre>
<pre style="background-color: white; font-family: consolas; font-size: 13px;"><pre style="font-family: consolas;"> <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">ScriptsController</span> : <span style="color: #2b91af;">Controller</span>
{
[<span style="color: #2b91af;">ActionName</span>(<span style="color: #a31515;">"DynamicWithModel.js"</span>)]
<span style="color: blue;">public</span> <span style="color: #2b91af;">ActionResult</span> Dynamic(<span style="color: blue;">string</span> message)
{
<span style="color: blue;">return</span> <span style="color: blue;">this</span>.JavaScriptFromView(model:message);
}
<span style="color: blue;">public</span> <span style="color: #2b91af;">ActionResult</span> Index()
{
<span style="color: blue;">return</span> Content(<span style="color: #a31515;">"Scripts folder"</span>);
}
<span style="color: blue;">protected</span> <span style="color: blue;">override</span> <span style="color: blue;">void</span> HandleUnknownAction(<span style="color: blue;">string</span> actionName)
{
<span style="color: blue;">var</span> res = <span style="color: blue;">this</span>.<b>JavaScriptFromView</b>();
res.ExecuteResult(ControllerContext);
}
}</pre>
</pre>
<pre style="background-color: white; font-family: consolas; font-size: 13px;"></pre>
<pre style="background-color: white; font-family: consolas; font-size: 13px;">For DynamicWithModel.js i want to pass model, retrieving it from input parameter. In this case since I cannot create method containing dot in a name, I have to use attribute ActionName (alternatively I can avoid using dots in resource names in Index.chtml).</pre>
<pre style="background-color: white; font-family: consolas; font-size: 13px;"></pre>
<pre style="background-color: white; font-family: consolas; font-size: 13px;">In order to make these controllers handle requests with file extensions in URL you must modify your web.config:</pre>
<pre style="background-color: white; font-family: consolas; font-size: 13px;"></pre>
<br />
<pre style="background-color: white; font-family: consolas; font-size: 13px;"><span style="color: blue;"><</span><span style="color: #a31515;">system.webServer</span><span style="color: blue;">></span>
<span style="color: blue;"> <</span><span style="color: #a31515;">modules</span><span style="color: blue;"> </span><span style="color: red;">runAllManagedModulesForAllRequests</span><span style="color: blue;">=</span>"<span style="color: blue;">true</span>"<span style="color: blue;">/></span></pre>
<br />
<br />
<br />
<br />
<h3>
Implementing the "Magic" extensions:</h3>
<span style="background-color: white; font-family: consolas; font-size: 13px;"><br /></span><span style="background-color: white; font-family: consolas; font-size: 13px;">As you might notice I used custom controller extensions <b>JavaScriptFromView</b> and <b>CssFromView</b> - these guys do all the magic. Here is it's implementation:</span><br />
<span style="background-color: white; font-family: consolas; font-size: 13px;"><br /></span>
<br />
<pre><blockquote class="tr_bq">
<span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> System.Collections.Generic;
<span style="color: blue;">using</span> System.IO;
<span style="color: blue;">using</span> System.Linq;
<span style="color: blue;">using</span> System.Text.RegularExpressions;
<span style="color: blue;">using</span> System.Web;
<span style="color: blue;">namespace</span> System.Web.Mvc
{
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span><br />
<br />
<summary><span style="color: grey;">
</span></summary> <span style="color: grey;">///</span><span style="color: green;"> Mvc extensions for dynamic CSS and JS</span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span></blockquote>
</pre>
<br />
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">MvcExtensions</span> {<br />
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<summary><span style="color: grey;"><br /></span></summary> <span style="color: grey;">///</span><span style="color: green;"> CSS content result rendered by partial view specified</span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span><br />
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"controller"</span><span style="color: grey;">></span><span style="color: green;">current controller</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"cssViewName"</span><span style="color: grey;">></span><span style="color: green;">view name, which contains partial view with one STYLE block only</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"model"</span><span style="color: grey;">></span><span style="color: green;">optional model to pass to partial view for rendering</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><returns></returns><br /></span> <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: #2b91af;">ActionResult</span> CssFromView(<span style="color: blue;">this</span> <span style="color: #2b91af;">Controller</span> controller, <span style="color: blue;">string</span> cssViewName=<span style="color: blue;">null</span>, <span style="color: blue;">object</span> model=<span style="color: blue;">null</span>)<br /> {<br /> <span style="color: blue;">var</span> cssContent = ParseViewToContent(controller,cssViewName, <span style="color: #a31515;">"style"</span>, model);<br /> <span style="color: blue;">if</span>(cssContent==<span style="color: blue;">null</span>) <span style="color: blue;">throw</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">HttpException</span>(404,<span style="color: #a31515;">"CSS not found"</span>);<br /> <span style="color: blue;">return</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">ContentResult</span>() { Content = cssContent, ContentType = <span style="color: #a31515;">"text/css"</span> };<br /> }<br /> <br /> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span></span></span></span><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<summary><span style="color: grey;"><span style="color: grey;"><span style="color: grey;"><br /></span></span></span></summary><span style="color: grey;"><span style="color: grey;"> <span style="color: grey;">///</span><span style="color: green;"> Javascript content result rendered by partial view specified</span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span></span></span><br />
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"controller"</span><span style="color: grey;">></span><span style="color: green;">current controller</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"javascriptViewName"</span><span style="color: grey;">></span><span style="color: green;">view name, which contains partial view with one SCRIPT block only</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"model"</span><span style="color: grey;">></span><span style="color: green;">optional model to pass to partial view for rendering</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><returns></returns><br /></span> <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: #2b91af;">ActionResult</span> JavaScriptFromView(<span style="color: blue;">this</span> <span style="color: #2b91af;">Controller</span> controller, <span style="color: blue;">string</span> javascriptViewName=<span style="color: blue;">null</span>, <span style="color: blue;">object</span> model=<span style="color: blue;">null</span>)<br /> {<br /> <span style="color: blue;">var</span> jsContent = ParseViewToContent(controller,javascriptViewName, <span style="color: #a31515;">"script"</span>, model);<br /> <span style="color: blue;">if</span>(jsContent==<span style="color: blue;">null</span>) <span style="color: blue;">throw</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">HttpException</span>(404,<span style="color: #a31515;">"JS not found"</span>);<br /> <span style="color: blue;">return</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">JavaScriptResult</span>() {Script = jsContent };<br /> }<br /> <br /> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span></span></span></span><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<summary><span style="color: grey;"><span style="color: grey;"><span style="color: grey;"><br /></span></span></span></summary><span style="color: grey;"><span style="color: grey;"> <span style="color: grey;">///</span><span style="color: green;"> Parse view and render it to a string, trimming specified HTML tag</span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span></span></span><br />
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"controller"</span><span style="color: grey;">></span><span style="color: green;">controller which renders the view</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"viewName"</span><span style="color: grey;">></span><span style="color: green;">name of cshtml file with content. If null, then actionName used</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"tagName"</span><span style="color: grey;">></span><span style="color: green;">Content rendered expected to be wrapped with this html tag, and it will be trimmed from result</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><param name="</span" nbsp="" /><span style="color: grey;">"model"</span><span style="color: grey;">></span><span style="color: green;">model to pass for view to render</span><span style="color: grey;"><br /></span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><returns></returns><br /></span> <span style="color: blue;">static</span> <span style="color: blue;">string</span> ParseViewToContent(<span style="color: #2b91af;">Controller</span> controller, <span style="color: blue;">string</span> viewName, <span style="color: blue;">string</span> tagName, <span style="color: blue;">object</span> model = <span style="color: blue;">null</span>)<br /> {<br /> <span style="color: blue;">using</span> (<span style="color: blue;">var</span> viewContentWriter = <span style="color: blue;">new</span> <span style="color: #2b91af;">StringWriter</span>())<br /> {<br /> <span style="color: blue;">if</span> (model != <span style="color: blue;">null</span>)<br /> controller.ViewData.Model = model;<br /> <br /> <span style="color: blue;">if</span> (<span style="color: blue;">string</span>.IsNullOrEmpty(viewName))<br /> viewName = controller.RouteData.GetRequiredString(<span style="color: #a31515;">"action"</span>);<br /> <br /> <span style="color: blue;">var</span> viewResult = <span style="color: blue;">new</span> <span style="color: #2b91af;">ViewResult</span>()<br /> {<br /> ViewName = viewName,<br /> ViewData = controller.ViewData,<br /> TempData = controller.TempData,<br /> ViewEngineCollection = controller.ViewEngineCollection<br /> };<br /> <br /> <span style="color: blue;">var</span> viewEngineResult = controller.ViewEngineCollection.FindPartialView(controller.ControllerContext, viewName);<br /> <span style="color: blue;">if</span> (viewEngineResult.View == <span style="color: blue;">null</span>)<br /> <span style="color: blue;">return</span> <span style="color: blue;">null</span>;<br /> <br /> <span style="color: blue;">try</span> {<br /> <span style="color: blue;">var</span> viewContext = <span style="color: blue;">new</span> <span style="color: #2b91af;">ViewContext</span>(controller.ControllerContext, viewEngineResult.View, controller.ViewData, controller.TempData, viewContentWriter);<br /> viewEngineResult.View.Render(viewContext, viewContentWriter);<br /> <span style="color: blue;">var</span> viewString = viewContentWriter.ToString().Trim(<span style="color: #a31515;">'\r'</span>, <span style="color: #a31515;">'\n'</span>, <span style="color: #a31515;">' '</span>);<br /> <span style="color: blue;">var</span> regex = <span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"<{0}[^>]*>(.*?)</{0}>"</span>, tagName);<br /> <span style="color: blue;">var</span> res = <span style="color: #2b91af;">Regex</span>.Match(viewString, regex, <span style="color: #2b91af;">RegexOptions</span>.IgnoreCase | <span style="color: #2b91af;">RegexOptions</span>.IgnorePatternWhitespace | <span style="color: #2b91af;">RegexOptions</span>.Multiline | <span style="color: #2b91af;">RegexOptions</span>.Singleline);<br /> <span style="color: blue;">if</span> (res.Success && res.Groups.Count > 1)<br /> <span style="color: blue;">return</span> res.Groups[1].Value;<br /> <span style="color: blue;">else</span> <span style="color: blue;">throw</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">InvalidProgramException</span>(<span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"Dynamic content produced by viewResult '{0}' expected to be wrapped in '{1}' tag"</span>, viewName, tagName));<br /> }<br /> <span style="color: blue;">finally</span> {<br /> <span style="color: blue;">if</span> (viewEngineResult.View != <span style="color: blue;">null</span>)<br /> viewEngineResult.ViewEngine.ReleaseView(controller.ControllerContext, viewEngineResult.View);<br /> }<br /> }<br /> <br /> }<br /> <br /> }<br />}</span></span></span></span><br />
<pre style="background-color: white; font-family: consolas; font-size: 13px;"> </pre>
<pre style="background-color: white; font-family: consolas;"><div style="font-family: 'Times New Roman'; white-space: normal;">
<b><span style="font-size: large;">Show time</span></b></div>
<div>
</div>
<div style="font-family: 'Times New Roman'; font-size: medium; white-space: normal;">
</div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXfPoCSWmNKCdqd5cLOJzao5TRG-Ch4tsk_Z3Z-CyL-fc3m75f9F5RcK9dKoZc19kHQGmSUdQar2YSiBL7Q2bj1y91_ns0cIFeA-WXDI1s9vYFpRcQoKYC1usxUSgjC3zn5tz0mGEwIVaM/s1600-h/image%25255B24%25255D.png"><img alt="image" border="0" height="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2_mW5_KVSPBm6zNjqzGUC7wDg4RAZQRq0_sE6sEdyKSKdzv_mrWNrWDpVm1uc2SBBjJXwiWnqTk1J_ckRLc8NStxsFxHcJ1kH6U-ewcb5mzbN_Ei8lMEuaQfsH9PH5cKsmyAVLdSCuT_N/?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="520" /></a></div>
</pre>
<br />
As you can see you can modify query string parameters in runtime using IE Developer Tools:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyXg_Ry45JFqRdTn90L5nYwij7pWrHiJPCryFEJxFeCFZA-4ixjQPWLyag5gVaq34B7avDxkivIXc6tfx1I_XQJOd4luLfgRpoWUtyuhPu7k-f8NIB5hXCEhum_7g009k0mtgwstvnXBsr/s1600-h/image%25255B28%25255D.png"><img alt="image" border="0" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMfnLqi-y1qeKfoZbp9YRWEPUSHYBCpyRXeFhNXdV-OHp0AVYJHeE3rq59OWjv7uDRCkHrdanzK9luNhCqC8t0XO72RHHqr7fftzT9IJrqJhgWMlD8UwfGOcN0D_GcOMewQBkBpTT3Zh1W/?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="510" /></a><br />
<br />
<br />
and see results immediately:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSh14Pp4SRnXykEQQs4Y7fdSiyvcvJ6tz_Z2VC6t4YtYWgeLqI7FLWXpgrWdhElF2t2GTpOqnpnG6C-LaXHJ0KcIgXloVqTln2IQAH9m65juIiZqvfwonKAffdR_cJFyNJJEbkg5_yh-6t/s1600-h/image%25255B36%25255D.png"><img alt="image" border="0" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8ccw-qPFbsrG-vgDkjHEW3rBraLrY6qpPRwqJYa9jmbf2QIJFakU7kVCXAHvO4nZToNHPqbE15LIjn03PW3C8I0PTfG_V_sweaUwArObfYnWHlOSqTAwLVMnykIYlFzN0mVc8s-nrsktA/?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="520" /></a><br />
<br />
in Network tab you can see actual responses and low level information:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS221BsDQomxA2aVCN1QzEStGiiYhLeFoNMqI_q7CqbaOpUfPau-y5bnktCqtQ-cq_owlxlesgRqPs1TWbVoLKUdTVi7tVhQV3dyWVLU5zPTyRPkXXt9KisIDjIVNztf25r7KZH4_3gNbS/s1600-h/image%25255B16%25255D.png"><img alt="image" border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPt7mzlMdWnoxahGPyacUMuUycJEAmhNDHwfCPsuv4LYBrrtHoEJq9U7elRZo-bO2A7CmC-CKZP73Mgp1O81hJdLyXqo5styPSVDgT5iRvzaddR2fq7WkBXEChiUv-XdfXwTx2voGxzLFx/?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="507" /></a><br />
<br />
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY7CQJHpIbzN2RoqAG1i0dbNVC5Sm54a1uut7XZJSIfc_CvdSpj0TaqTYeMjviXcnZnIFk1FLuF-XGq_CHRVDG_mfmJ6kweLQHyEH2ILagJbmtWWxh5u__rp8N6h97EAF-6AtCKIgXbMO8/s1600-h/image%25255B20%25255D.png"><img alt="image" border="0" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxCEWQZgQXUBrkEMfYUy_e135pRhrCVODBBQrtAr8OxnZiimf9JHHGkiLcsvrFwLixt2NH4L529dkFXSuhGBmjduJ6byCpaUw-jKfRl-DwFH8fmkNSPPeSVEFebAUv84Y6_HEhEPjE1vI2/?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="495" /></a><br />
<br />
<br />
Dynamic Javascript response:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEims5MQ-407pvgIF5ZaoMozpqayKq0hX0Qax0C_XWnridndlCQIujfCnG6OWwogSzkuYn68LfWa2VZvOnZA7-XH8P7PDxUvmq_bLQ38LLALYXsQdwebW7cTojSF6yIJvzAnAGqUHPPJaiTH/s1600-h/image%25255B40%25255D.png"><img alt="image" border="0" height="129" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvpEwLmao0TwgZyTKn1tVgU6SSlGfQhno6aR1Sqh7UF1i0HI804oZ6CenT5rT7M8u1EvHZzH6pENLWtNKHTP2hHZV2An4C4Ix6I94CN-v3arqyqYPZuXULQfh0O61dH8y7JTEb6wqmzKCp/?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="503" /></a><br />
<br />
<br />
<i><u>Again, you can download source code from <a href="https://drive.google.com/file/d/0Bxp4SNNLrAEEVmNkekZ5cV82ZDA/view?usp=share_link&resourcekey=0-OcsdrSJHTu08CoH6_hYtNw"><b><span style="font-size: large;">here</span></b></a></u></i>.<br />
<br />
<span style="font-size: large;">Additional tricks:</span><br />
<br />
Since you can add inline code actually inline you probably won't need it, but You also can use those controllers' actions as child actions to render inline resources if you need using Html.RenderAction/ Html.Action(...) extensions on your parent HTML view. If you do this make sure your Response.ContentType is not overwritten by Render action and if it was you need manually to restore it.<br />
<br />
<br />
<span style="font-size: large;">FileHandler VS Controller competition for handling file request</span><br />
<br />
<br />
If you noticed there is a competition between Static file Handler and your Controller for handling requests to resource file (js/css). So it is important to understand how it works. So here it is:<br />
<br />
By default StaticFileHandler has priority. This means if you create file <b>~/Views/Scripts/static.js.cshtml</b>, and you already have file <b>~/Scripts/static.js</b> - the last one (real static) will be used. But you can change this behavior using Routing. You need to do is to add in your RouteConfig.cs (located in App_Start for MVC4 template) the following line:<br />
<br />
<pre style="background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"> routes.RouteExistingFiles = <span style="color: blue;">true</span>;
</pre>
<br />
<br />
It will deactivate Static File handler and redirect all file requests to Controllers.Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-59904195982206489622012-08-28T04:59:00.000-04:002012-08-28T05:00:07.171-04:00XAML Explicit binding to Interface - Object 'null' cannot be used as an accessor parameter for a PropertyPath - Version 2This is evolution of my previous post: <a href="http://blog.pmunin.com/2012/02/xaml-explicit-binding-to-interface.html">http://blog.pmunin.com/2012/02/xaml-explicit-binding-to-interface.html</a><br />
I've decided not to overwrite the old one, but create new post instead.<br />
<br />
So eventually I decided to resolve issue using separate binding class, which is inherited from Binding, but contains all necessary improvements.<br />
<blockquote class="tr_bq">
<br /><span style="color: blue;">using</span> System;<br /><span style="color: blue;">using</span> System.Collections.Generic;<br /><span style="color: blue;">using</span> System.Linq;<br /><span style="color: blue;">using</span> System.Text;<br /><span style="color: blue;">using</span> System.Windows;<br /><span style="color: blue;">using</span> System.Windows.Markup;<br /><span style="color: blue;">using</span> System.Windows.Data;<br /><span style="color: blue;">using</span> System.Diagnostics;<br /><span style="color: blue;">using</span> System.ComponentModel;<br /> [<span style="color: blue;">assembly</span>: <span style="color: #2b91af;">XmlnsDefinition</span>(<span style="color: #a31515;">"http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span>, <span style="color: #a31515;">"PMunin.com"</span>)]<br /><span style="color: blue;">namespace</span> PMunin.com<br />{<br /> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><summary><br /></summary></span> <span style="color: grey;">///</span><span style="color: green;"> Inherited from Binding, have some improvements:</span> <span style="color: grey;">///</span><span style="color: green;"> - does not crash VS2010 WPF designer if Path contains Interface.</span> <span style="color: grey;">///</span><span style="color: green;"> - ValidateOnDataErrors and ValidateOnExceptions are true by default.</span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span></blockquote>
<br /> <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">XamlExtBinding</span> : <span style="color: #2b91af;">Binding</span><br /> {<br /> <span style="color: blue;">public</span> XamlExtBinding():<span style="color: blue;">base</span>()<br /> {<br /> NotifyOnValidationError = <span style="color: blue;">true</span>;<br /> ValidatesOnDataErrors = <span style="color: blue;">true</span>;<br /> ValidatesOnExceptions = <span style="color: blue;">true</span>;<br /> }<br /> <span style="color: blue;">public</span> XamlExtBinding(<span style="color: blue;">string</span> path):<span style="color: blue;">base</span>(path)<br /> {<br /> NotifyOnValidationError = <span style="color: blue;">true</span>;<br /> ValidatesOnDataErrors = <span style="color: blue;">true</span>;<br /> ValidatesOnExceptions = <span style="color: blue;">true</span>;<br /> }<br /> [<span style="color: #2b91af;">TypeConverter</span>(<span style="color: blue;">typeof</span>(<span style="color: #2b91af;">ExtPropertyPathConverter</span>))]<br /> <span style="color: blue;">public</span> <span style="color: blue;">new</span> <span style="color: blue;">object</span> Path<br /> {<br /> <span style="color: blue;">get</span><br /> {<br /> <span style="color: blue;">return</span> <span style="color: blue;">base</span>.Path;<br /> }<br /> <span style="color: blue;">set</span><br /> {<br /> <span style="color: blue;">base</span>.Path = <span style="color: blue;">value</span> <span style="color: blue;">as</span> <span style="color: #2b91af;">PropertyPath</span>;<br /> }<br /> }<br /> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><summary><br /></summary></span> <span style="color: grey;">///</span><span style="color: green;"> Required to fix bug "Prefix 'local' does not map to a namespace"</span> <span style="color: grey;">///</span><span style="color: green;"> when Path with namespace used in DataTemplate like here (http://devexpress.com/Support/Center/p/Q352753.aspx)</span> <span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span><br /> <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">ExtPropertyPathConverter</span> : <span style="color: #2b91af;">TypeConverter</span> {<br /> <span style="color: blue;">static</span> <span style="color: #2b91af;">PropertyPathConverter</span> pathConverter = <span style="color: blue;">new</span> <span style="color: #2b91af;">PropertyPathConverter</span>();<br /> <span style="color: blue;">static</span> <span style="color: blue;">bool</span> IsInDesignMode(<span style="color: #2b91af;">ITypeDescriptorContext</span> context)<br /> {<br /> <span style="color: blue;">bool</span> isInDesignMode = <span style="color: #2b91af;">DesignerProperties</span>.GetIsInDesignMode(<span style="color: #2b91af;">Application</span>.Current.MainWindow);<br /> <span style="color: blue;">return</span> isInDesignMode;<br /> }<br /> <span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">bool</span> CanConvertFrom(<span style="color: #2b91af;">ITypeDescriptorContext</span> context, <span style="color: #2b91af;">Type</span> sourceType)<br /> {<br /> <span style="color: blue;">bool</span> res = <span style="color: blue;">true</span>;<br /> <span style="color: blue;">try</span> {<br /> res = pathConverter.CanConvertFrom(context, sourceType);<br /> }<br /> <span style="color: blue;">catch</span> {<br /> <span style="color: blue;">if</span> (!IsInDesignMode(context)) <span style="color: blue;">throw</span>;<br /> }<br /> <span style="color: blue;">return</span> res;<br /> }<br /> <span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">bool</span> CanConvertTo(<span style="color: #2b91af;">ITypeDescriptorContext</span> context, <span style="color: #2b91af;">Type</span> destinationType)<br /> {<br /> <span style="color: blue;">var</span> res = <span style="color: blue;">true</span>;<br /> <span style="color: blue;">try</span> {<br /> res = pathConverter.CanConvertTo(context, destinationType);<br /> }<br /> <span style="color: blue;">catch</span> {<br /> <span style="color: blue;">if</span> (!IsInDesignMode(context)) <span style="color: blue;">throw</span>;<br /> }<br /> <span style="color: blue;">return</span> res;<br /> }<br /> <span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">object</span> ConvertFrom(<span style="color: #2b91af;">ITypeDescriptorContext</span> context, System.Globalization.<span style="color: #2b91af;">CultureInfo</span> culture, <span style="color: blue;">object</span> value)<br /> {<br /> <span style="color: blue;">object</span> res = <span style="color: blue;">null</span>;<br /> <span style="color: blue;">try</span> {<br /> res = pathConverter.ConvertFrom(context, culture, value);<br /> }<br /> <span style="color: blue;">catch</span> {<br /> <span style="color: blue;">if</span> (!IsInDesignMode(context)) <span style="color: blue;">throw</span>;<br /> }<br /> <span style="color: blue;">return</span> res;<br /> }<br /> <span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">object</span> ConvertTo(<span style="color: #2b91af;">ITypeDescriptorContext</span> context, System.Globalization.<span style="color: #2b91af;">CultureInfo</span> culture, <span style="color: blue;">object</span> value, <span style="color: #2b91af;">Type</span> destinationType)<br /> {<br /> <span style="color: blue;">object</span> res = <span style="color: blue;">null</span>;<br /> <span style="color: blue;">try</span> {<br /> res = pathConverter.ConvertTo(context, culture, value, destinationType);<br /> }<br /> <span style="color: blue;">catch</span> {<br /> <span style="color: blue;">if</span> (!IsInDesignMode(context)) <span style="color: blue;">throw</span>;<br /> }<br /> <span style="color: blue;">return</span> res;<br /> }<br /> }<br /> }<br /> }<br />
<pre style="background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;">
</pre>
<pre style="background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;">
</pre>
<pre style="background-color: white; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><div style="font-family: 'Times New Roman'; font-size: medium; white-space: normal;">
You should put this class in separate shared class library, that is referenced by you project with XAML files you need to edit. This will allow you to use in very simple way you get used to - anywhere you have {Binding ....}, or <binding ....="...."> just replace it with {XamlExtBinding ...} or <xamlextbinding ...="...">. No namespace declaration required.</xamlextbinding></binding></div>
<div style="font-family: 'Times New Roman'; font-size: medium; white-space: normal;">
</div>
<div style="font-family: 'Times New Roman'; font-size: medium; white-space: normal;">
This code was written long time ago, so I'm posting it now, but I'm not sure that included everything. Please feel free to comment - if you face any issues.</div>
</pre>
Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-81864366493961056192012-02-20T18:51:00.002-05:002012-02-21T19:23:55.084-05:00XAML binding to CompositeCollectionSome times there is a need to display in your ItemsControl (like TreeView or ListBox) some compound collection, which consists from several collections of elements.<br />
Well, microsoft provides us CompositeCollection and CollectionContainer classes for this purpose. However it is a real pain to use data binding with this classes in XAML. Here is one of solution suggested, which looks a bit ugly if you ask me: <a href="http://wilberbeast.com/2011/05/31/compositecollection-binding-problem/">http://wilberbeast.com/2011/05/31/compositecollection-binding-problem/</a><br />
<br />
I'll show you alternative you can use to make it looks a bit better and neat.<br />
<br />
For example I have a view model of Survey, which has properties:<br />
<br />
<i>public class SurveyViewModel{</i><br />
<i> public InstructionsModel Instructions {get;}</i><br />
<i> public ObservableCollection<QuestionModel><questionmodel> Children {get;}</questionmodel></i><br />
<i> public ReviewModel Review {get;}</i><br />
<i>}</i><br />
<br />
And I need to display in a listbox the following items:<br />
<b><i>[Instructions]</i></b><br />
<b><i>[Question1]</i></b><br />
<br />
<b><i>[Question2]</i></b><br />
<b><i>...</i></b><br />
<b><i>[QuestionN]</i></b><br />
<b><i>[Review]</i></b><br />
<div>
<br /></div>
<div>
I keep in mind that Children collection can be updated - in that case ListBox must be automagically refreshed (new element might be added/removed by some action buttons).
</div>
I want to each item to be displayed in a different manner based on its type and associated DataTemplate.In order to do that, i need to assign in myListBox.ItemsSource to CompositeCollection with CollectionContainers inside. But if you will try it you will see how many gabage you will have to put in different parts of your XAML. Here is the alternative approach how I do it now:<br />
<br />
<pre style="background-attachment: initial; background-clip: initial; background-color: #fff7df; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"><span style="color: blue;"><</span><span style="color: #a31515;">TreeView</span>
<span style="color: red;"> x</span><span style="color: blue;">:</span><span style="color: red;">Name</span><span style="color: blue;">=</span><span style="color: blue;">"tvSurvey"</span><span style="color: blue;">></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">TreeView.ItemsSource</span><span style="color: blue;">></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">MultiBinding</span><span style="color: blue;">></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">MultiBinding.Converter</span><span style="color: blue;">></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">local</span><span style="color: blue;">:</span><span style="color: #a31515;">CompositeCollectionConverter</span><span style="color: blue;"> /></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><span style="color: #a31515;">MultiBinding.Converter</span><span style="color: blue;">></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">Binding</span><span style="color: red;"> Path</span><span style="color: blue;">=</span><span style="color: blue;">"ViewModel.Instructions"</span><span style="color: blue;"> /></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">Binding </span><span style="color: red;">Path</span><span style="color: blue;">=</span><span style="color: blue;">"ViewModel.Children"</span><span style="color: blue;"> /></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">Binding</span> <span style="color: red;">Path</span><span style="color: blue;">=</span><span style="color: blue;">"ViewModel.Review"</span><span style="color: blue;"> /></span>
</span><span style="color: blue;"><span style="color: blue;"><span style="color: blue;"><span style="color: blue;"> </</span></span></span></span><span style="color: #a31515;">MultiBinding</span><span style="color: blue;">>
</span><span style="color: blue;"><span style="color: blue;"><span style="color: blue;"><span style="color: blue;"> </T</span></span></span></span><span style="color: #a31515;">reeView.ItemsSource</span><span style="color: blue;">>
</span>...
TreeView.Resources with datatemplates for:
InstructionsModel, QuestionModel, ReviewModel
...
<span style="color: blue;"></</span><span style="color: blue;"><span style="color: #a31515;">TreeView></span></span></pre>
</pre>
<br />
As you already may see there is no magic here: just use MultiBinding, which supports current DataContext (<i><u>unlike CollectionContainer</u></i>) plus CompositeCollectionConverter (IMultiValueConverter) for converting multibinding to composite collection.<br />
<br />
Here is the code of CompositeCollectionConverter:<br />
<br />
<br />
<pre style="background-attachment: initial; background-clip: initial; background-color: #fff7df; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"> <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">CompositeCollectionConverter</span>:<span style="color: #2b91af;">IMultiValueConverter</span>
{
<span style="color: blue;">public</span> <span style="color: blue;">object</span> Convert(<span style="color: blue;">object</span>[] values
, <span style="color: #2b91af;">Type</span> targetType
, <span style="color: blue;">object</span> parameter
, System.Globalization.<span style="color: #2b91af;">CultureInfo</span> culture)
{
<span style="color: blue;">var</span> res = <span style="color: blue;">new</span> <span style="color: #2b91af;">CompositeCollection</span>();
<span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> item <span style="color: blue;">in</span> values)
<span style="color: blue;">if</span> (item <span style="color: blue;">is</span> <span style="color: #2b91af;">IEnumerable</span>)
res.Add(<span style="color: blue;">new</span> <span style="color: #2b91af;">CollectionContainer</span>()
{
Collection = item <span style="color: blue;">as</span> <span style="color: #2b91af;">IEnumerable</span>
});
<span style="color: blue;">else</span> res.Add(item);
<span style="color: blue;">return</span> res;
}
<span style="color: blue;">public</span> <span style="color: blue;">object</span>[] ConvertBack(<span style="color: blue;">object</span> value
, <span style="color: #2b91af;">Type</span>[] targetTypes
, <span style="color: blue;">object</span> parameter
, System.Globalization.<span style="color: #2b91af;">CultureInfo</span> culture)
{
<span style="color: blue;">throw</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">NotImplementedException</span>();
}
}</pre>
</pre>
<br />
<br />
<br />
Enjoy :-)Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-75111062140079129962012-02-20T18:10:00.003-05:002012-08-28T05:02:57.460-04:00XAML Explicit binding to Interface - Object 'null' cannot be used as an accessor parameter for a PropertyPath<br />
<b><i>Object 'null' cannot be used as an accessor parameter for a PropertyPath. An accessor parameter must be DependencyProperty, PropertyInfo, or PropertyDescriptor.</i></b><br />
<br />
<h4>
Note: Implementation of this post is obsolete. Please see new version here: <a href="http://blog.pmunin.com/2012/08/xaml-explicit-binding-to-interface.html">http://blog.pmunin.com/2012/08/xaml-explicit-binding-to-interface.html</a></h4>
<br />
Everyone who works with MVVM pattern in WPF had met this problem with data binding to interface property. When you use bindin with explicit PropertyPath (like <b>Path=(local:IMyInterface.MyProperty)</b>) your designer is no longer working (neither Visual Studio XAML, nor Expression Blend).<br />
<br />
The interesting/weird thing is that it screw up only if you use this binding in visual tree of your user control or windows, but not in DataTemplate/HierarchicalDataTemplate. Explicit binding inside DataTemplate works fine for me.<br />
<br />
<br />
Finally I've found some workaround solution that allows you to use binding to interfaces' properties without breaking you Visual Studio and Expression Blend designers in main visual tree. But you will have to add something to your XAML. Basically instead of writing <b>Path=(local:IMyInterface.MyProperty)</b>, you will have to write <b>XamlExt.Path=(local:IMyInterface.MyProperty)</b>.<br />
<br />
This is how you can achieve it:<br />
1) Create Attached Property to Binding class.<br />
2) Register Xml namespace mapping.<br />
3) Enjoy full MVVM pattern in your Xaml applications with working designer<br />
<br />
Here is code of XAML Markup Extension <b>in separate class library</b>:<br />
<br />
<pre style="background-attachment: initial; background-clip: initial; background-color: #fff7df; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"><span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> System.Collections.Generic;
<span style="color: blue;">using</span> System.Linq;
<span style="color: blue;">using</span> System.Text;
<span style="color: blue;">using</span> System.Windows;
<span style="color: blue;">using</span> System.Windows.Markup;
<span style="color: blue;">using</span> System.Windows.Data;
<span style="color: blue;">using</span> System.Diagnostics;
<span style="color: blue;">using</span> System.ComponentModel;
<span style="color: blue;">namespace</span> MyWPFApplication.Extensions
{
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><summary>
<span style="color: grey;">///</span><span style="color: green;"> Binding extensions required to bind to interface property </span></summary></span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"><span style="color: green;"> /// without breaking designer</span>
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span>
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">partial</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">XamlExt</span>
{
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">object</span> GetPath(System.Windows.Data.<span style="color: #2b91af;">Binding</span> obj)
{
<span style="color: blue;">return</span> obj.Path;
}
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> SetPath(System.Windows.Data.<span style="color: #2b91af;">Binding</span> obj, <span style="color: blue;">object</span> value)
{
<span style="color: blue;">try</span>
{
obj.Path = (<span style="color: #2b91af;">PropertyPath</span>)value;
}
<span style="color: blue;">catch</span> (<span style="color: #2b91af;">Exception</span> e)
{
<span style="color: #2b91af;">PresentationTraceSources</span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"> .DataBindingSource</pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"> .TraceData(<span style="color: #2b91af;">TraceEventType</span>.Error, 0, e);
<span style="color: blue;">throw</span>;
}
}
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">readonly</span> <span style="color: #2b91af;">DependencyProperty</span> PathProperty =
<span style="color: #2b91af;">DependencyProperty</span>.RegisterAttached(<span style="color: #a31515;">"Path"</span>, </pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"><span style="color: blue;"> typeof</span>(<span style="color: #2b91af;">PropertyPath</span>)</pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"> , <span style="color: blue;">typeof</span>(<span style="color: #2b91af;">XamlExt</span>)</pre>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas;"> , <span style="color: blue;">new</span> <span style="color: #2b91af;">PropertyMetadata</span>());
}
}
</pre>
</pre>
<br />
<br />
In order to use it conveniently in you XAML, you just need to add attribute in Assembly.cs:<br />
<br />
<pre style="background-attachment: initial; background-clip: initial; background-color: #fff7df; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;">[<span style="color: blue;">assembly</span>: <span style="color: #2b91af;">XmlnsDefinition</span>(<span style="color: #a31515;">"http://schemas.microsoft.com/winfx/2006/xaml/presentation"</span></pre>
<pre style="background-attachment: initial; background-clip: initial; background-color: #fff7df; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;">, <span style="color: #a31515;">"MyWPFApplication.Extensions"</span>)]</pre>
<br />
<br />
<br />
Now add modification to your old code.<br />
<b>Old code</b>:<br />
<br />
<pre style="background-attachment: initial; background-clip: initial; background-color: #fff7df; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"><span style="color: blue;"><</span><span style="color: #a31515;">Button</span>
<span style="color: red;">x</span><span style="color: blue;">:</span><span style="color: red;">Name</span><span style="color: blue;">=</span><span style="color: blue;">"btnAdd"</span>
<span style="color: red;">Content</span><span style="color: blue;">=</span><span style="color: blue;">"Add"</span>
<span style="color: red;">Command</span><span style="color: blue;">="{</span><span style="color: #a31515;">Binding</span><span style="color: red;"> Path</span><span style="color: blue;">=(</span><span style="color: blue;">local</span><span style="color: blue;">:</span><span style="color: blue;">IViewModel</span><span style="color: blue;">.</span><span style="color: blue;">AddCommand</span><span style="color: blue;">)}</span><span style="color: blue;">"</span><span style="color: blue;"> /></span></pre>
<br />
<br />
<b>New code</b>:<br />
<br />
<br />
<pre style="background-attachment: initial; background-clip: initial; background-color: #fff7df; background-image: initial; background-origin: initial; font-family: Consolas; font-size: 13px;"><span style="color: blue;"><</span><span style="color: #a31515;">Button</span>
<span style="color: red;">x</span><span style="color: blue;">:</span><span style="color: red;">Name</span><span style="color: blue;">=</span><span style="color: blue;">"btnAdd"</span>
<span style="color: red;">Content</span><span style="color: blue;">=</span><span style="color: blue;">"Add"</span>
<span style="color: red;">Command</span><span style="color: blue;">="{</span><span style="color: #a31515;">Binding</span><span style="color: red;"> XamlExt</span><span style="color: blue;">.Path=(</span><span style="color: blue;">local</span><span style="color: blue;">:</span><span style="color: blue;">IViewModel</span><span style="color: blue;">.</span><span style="color: blue;">AddCommand</span><span style="color: blue;">)}</span><span style="color: blue;">"</span><span style="color: blue;"> /></span></pre>
<br />
<br />
<br />
<br />
<h4>
Note: Implementation of this post is obsolete. Please see new version here: <a href="http://blog.pmunin.com/2012/08/xaml-explicit-binding-to-interface.html">http://blog.pmunin.com/2012/08/xaml-explicit-binding-to-interface.html</a></h4>
<br class="Apple-interchange-newline" />Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-5044649566211309012012-01-27T22:41:00.001-05:002012-01-28T02:00:06.284-05:00XAML DataTemplates binding to interfaceSome times it is much convenient to use interface as a View Model for a View. In WinForms there was no problem with it (using BindingSource for instance), but in WPF DataBinding engine is limited.<br />
Let's say you have any TreeView (the same works for ListBox, any ItemsControl or ContentControl, ContentPresenter - whatever has *TemplateSelector property). And you want nodes of this TreeView to display different content using different DataTemplates. And you want these DataTemplates to by mapped be bounded to Interface, instead of class. Another words View Model of each node datatemplate is defined by interface.<br />
<br />
So here is the solution to achieve it.<br />
<br />
I've created an MarkupExtension, that allows to assign very easily TemplateSelector, which will select appropriate datatemplate based on compatibility of interface.<br />
The XAML will look like this:<br />
<br />
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">ListBox</span>
<span style="color: red;"> ItemsSource</span><span style="color: blue;">="{</span><span style="color: #a31515;">Binding</span><span style="color: red;"> Source</span><span style="color: blue;">={</span><span style="color: #a31515;">StaticResource</span><span style="color: red;"> nodes</span><span style="color: blue;">}}</span><span style="color: blue;">"</span>
<span style="color: red;"> ItemTemplateSelector</span><span style="color: blue;">=<strong>"{</strong></span><strong><span style="color: #a31515;">local</span><span style="color: blue;">:</span><span style="color: #a31515;">InterfaceTemplateSelector</span><span style="color: red;"> nodeDataTemplate</span><span style="color: blue;">}</span><span style="color: blue;">"</span></strong>
</pre><pre style="background: white; color: black; font-family: Consolas;"> <span style="color: blue;"> ></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">ListBox.Resources</span><span style="color: blue;">></span>
</pre><span style="color: #a31515;"></span><br />
<span style="color: #a31515;"><pre style="background: white; color: black; font-family: Consolas;"><span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">HierarchicalDataTemplate</span>
<span style="color: red;"> x</span><span style="color: blue;">:</span><span style="color: red;">Key</span><span style="color: blue;">=</span><span style="color: blue;">"nodeDataTemplate"</span>
<span style="color: red;"> DataType</span><span style="color: blue;">="{</span><span style="color: #a31515;">x</span><span style="color: blue;">:</span><span style="color: #a31515;">Type</span><span style="color: red;"> local</span><span style="color: blue;">:</span><span style="color: red;">INode</span><span style="color: blue;">}</span><span style="color: blue;">"</span>
<span style="color: red;"> ItemsSource</span><span style="color: blue;">="{</span><span style="color: #a31515;">Binding</span><span style="color: blue;"> Path=(</span><span style="color: blue;">local</span><span style="color: blue;">:</span><span style="color: blue;">INode</span><span style="color: blue;">.</span><span style="color: blue;">Children</span><span style="color: blue;">)}</span><span style="color: blue;">"</span>
<span style="color: blue;"> >...</span>
</pre><pre style="background: white; color: black; font-family: Consolas;"><span style="color: #a31515;"> </span><span style="color: blue;"><span style="color: #a31515;">HierarchicalDataTemplate</span><span style="color: blue;">></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><span style="color: #a31515;">ListBox.Resources</span><span style="color: blue;">></span>
<span style="color: #a31515;"> </span><span style="color: blue;"><span style="color: #a31515;">ListBox</span><span style="color: blue;">></span>
</span></span></span></pre></span><br />
If you want to have several templates for different nodes than you will need the following XAML modifications:<br />
For ListBox you will have to change property <span style="color: red;">ItemTemplateSelector</span><span style="color: blue;">=<strong>"{</strong></span><strong><span style="color: #a31515;">local</span><span style="color: blue;">:</span><span style="color: #a31515;">InterfaceTemplateSelector</span><span style="color: red;"> 'rootNodeDataTemplate,nodeDataTemplate'</span><span style="color: blue;">}</span><span style="color: blue;">"</span></strong> <br />
and create second data template:<br />
<span style="color: #a31515;"> </span><span style="color: blue;"><</span><span style="color: #a31515;">HierarchicalDataTemplate</span><br />
<span style="color: red;"> x</span><span style="color: blue;">:</span><span style="color: red;">Key</span><span style="color: blue;">=</span><span style="color: blue;">"rootNodeDataTemplate"</span><br />
<span style="color: red;"> DataType</span><span style="color: blue;">="{</span><span style="color: #a31515;">x</span><span style="color: blue;">:</span><span style="color: #a31515;">Type</span><span style="color: red;"> <strong>local</strong></span><strong><span style="color: blue;">:</span><span style="color: red;">IRootNode</span></strong><span style="color: blue;">}</span><span style="color: blue;">"</span><br />
<span style="color: red;"> ItemsSource</span><span style="color: blue;">="{</span><span style="color: #a31515;">Binding</span><span style="color: blue;"> Path=(</span><span style="color: blue;">local</span><span style="color: blue;">:</span><span style="color: blue;">IRootNode</span><span style="color: blue;">.</span><span style="color: blue;">Children</span><span style="color: blue;">)}</span><span style="color: blue;">">....</span><br />
InterfaceTemplateSelector has two properties: <br />
1) ResourceKeys (also first constructor parameter) <br />
2) ResourceKeysSeparator (also second optional constructor parameter) - default value ","<br />
InterfaceTemplateSelector initialization parameter is CSV-string representing keys of resources which are data templates targeted to Interface.<br />
<br />
This selector will take all available resource DataTemplates and check DataType each of it (which should have interface assigned) against type of content Item that is about to render.<br />
Keep in mind that sequence of keys in InterfaceTemplateSelector defines priority of associating DataTemplate for content Item. Let's say you have Item that implement both interfaces (INode and IRootNode). But in our case it will get rootNodeDataTemplate assigned, because its key mentioned first.<br />
<br />
Here is the implementation the markup extension, to make it work accordingly:<br />
<br />
<pre style="background: white; color: black; font-family: Consolas;"> <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">InterfaceTemplateSelectorExtension</span> : System.Windows.Markup.<span style="color: #2b91af;">MarkupExtension</span>
{
<span style="color: blue;">public</span> InterfaceTemplateSelectorExtension()
{
ResourceKeysSeparator = <span style="color: #a31515;">","</span>;
}
<span style="color: blue;">public</span> <span style="color: blue;">string</span> ResourceKeysSeparator { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }
<span style="color: blue;">public</span> InterfaceTemplateSelectorExtension(<span style="color: blue;">string</span> resourceKeysCSV)
{
ResourceKeys = resourceKeysCSV;
}
<span style="color: blue;">public</span> InterfaceTemplateSelectorExtension(<span style="color: blue;">string</span> resourceKeys, <span style="color: blue;">string</span> separator)
{
ResourceKeys = resourceKeys;
ResourceKeysSeparator = separator;
}
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"><summary></summary></span>
<span style="color: grey;">///</span><span style="color: green;"> Comma separated resource keys specifying keys of DataTemplates that binds to interface</span>
<span style="color: grey;">///</span><span style="color: green;"> </span><span style="color: grey;"></span>
<span style="color: blue;">public</span> <span style="color: blue;">string</span> ResourceKeys { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }
<span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">object</span> ProvideValue(<span style="color: #2b91af;">IServiceProvider</span> serviceProvider)
{
<span style="color: blue;">return</span> <span style="color: blue;">new</span> <span style="color: #2b91af;">InterfaceTemplateSelector</span>(ResourceKeys.Split(<span style="color: blue;">new</span> <span style="color: blue;">string</span>[]{ResourceKeysSeparator}, <span style="color: #2b91af;">StringSplitOptions</span>.RemoveEmptyEntries));
}
<span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">InterfaceTemplateSelector</span>:<span style="color: #2b91af;">DataTemplateSelector</span>
{
<span style="color: blue;">string</span>[] resourceKeys;
<span style="color: blue;">public</span> InterfaceTemplateSelector(<span style="color: blue;">string</span>[] resourceKeys)
{
<span style="color: blue;">this</span>.resourceKeys = resourceKeys;
}
<span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: #2b91af;">DataTemplate</span> SelectTemplate(<span style="color: blue;">object</span> item, <span style="color: #2b91af;">DependencyObject</span> container)
{
<span style="color: blue;">var</span> c = (<span style="color: #2b91af;">FrameworkElement</span>)container;
<span style="color: blue;">var</span> dataTemplates = (<span style="color: blue;">from</span> rk <span style="color: blue;">in</span> resourceKeys
<span style="color: blue;">let</span> resource = c.TryFindResource(rk)
<span style="color: blue;">where</span> resource <span style="color: blue;">is</span> <span style="color: #2b91af;">DataTemplate</span>
<span style="color: blue;">where</span> (resource <span style="color: blue;">as</span> <span style="color: #2b91af;">DataTemplate</span>).DataType <span style="color: blue;">is</span> <span style="color: #2b91af;">Type</span>
<span style="color: blue;">select</span> resource).Cast<<span style="color: #2b91af;">DataTemplate</span>>()
;
<span style="color: blue;">var</span> itemType = item.GetType();
<span style="color: blue;">var</span> result = dataTemplates.FirstOrDefault(dt =>
(dt.DataType <span style="color: blue;">as</span> <span style="color: #2b91af;">Type</span>).IsInstanceOfType(item)
);
<span style="color: blue;">return</span> result??<span style="color: blue;">base</span>.SelectTemplate(item, container);
}
}
}
</pre>Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-42335524575504347572011-08-23T20:17:00.002-04:002011-08-23T23:43:59.189-04:00cache.Get(()=>GetLongRunningDataCall(…)) - Cache service based on lambda expressions<p>On current project I’m working with a web farm and long running backend web services. So we have to cache all web-service calls in our distributed cache. Distributed cache can store only serializable objects of course.</p> <p>Lets say we have long running method “GetCustomerInformation(string customerId, Language language)” which returns some huge object graph based on input parameters.</p> <p>With current implementation we have to wrap all operation calls by this template:</p> <hr> <blockquote><pre class="csharpcode">CustomerInfo GetCustomerInfoCached(<span class="kwrd">string</span> customerId, Language language)<br />{<br /> var res = TryGetFromCache<CustomerInfo>(<span class="kwrd">out</span> wasInCache, “GetCustomerInformation”, customerId, language);<br /> <span class="kwrd">if</span>(wasInCache) <span class="kwrd">return</span> res;<br /> res= GetCustomerInformation(customerId,language); <span class="rem">//long running call</span><br /> StoreInCache<CustomerInfo>(res, “GetCustomerInformation”, customerId, language);<br /> <span class="kwrd">return</span> res;<br />}<br /></pre></blockquote><br /><hr><br /><br /><p>Let’s say I would like to replace all this code with something like this:</p><br /><blockquote><br /><p><strong><font size="2">var res = cache.Get(()=>GetCustomerInfo(customerId,language));</font></strong></p></blockquote><br /><p>Where this cache.Get(…) will do internally all this crap you see in the first code block. Can I do this? Like Obama says “Yes I can!”. And here is the way to do this, which use <a href="http://blog.pmunin.com/2011/08/gethashcode-for-serializable-object.html" target="_blank">GetHashCode extension</a>:</p><br /><hr><br /><pre class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.Linq;<br /><span class="kwrd">using</span> System.Linq.Expressions;<br /><span class="kwrd">using</span> System.Text;<br /><span class="kwrd">using</span> System.Collections;<br /><br /><span class="kwrd">namespace</span> PMunin.com<br />{<br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Cache service that supports Lambda expression</span><br /> <span class="rem">/// </summary></span><br /> <span class="kwrd">public</span> <span class="kwrd">class</span> Cache<br /> {<br /><br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Fake operation required to make GetParameterKey working</span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <param name="pars"></param></span><br /> <span class="rem">/// <returns></returns></span><br /> <span class="kwrd">static</span> <span class="kwrd">object</span>[] GetParameterValues(<span class="kwrd">params</span> <span class="kwrd">object</span>[] pars)<br /> {<br /> <span class="kwrd">return</span> pars;<br /> }<br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Get instantiated parameter values of specified method call expression. </span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <typeparam name="T"></typeparam></span><br /> <span class="rem">/// <param name="parametrizedMethodCall">Method call Lambda expression. Like "()=>GetSomeLongExecutedFunction(par1,par2,"par3",...)"</param></span><br /> <span class="rem">/// <returns></returns></span><br /> <span class="kwrd">protected</span> <span class="kwrd">object</span>[] GetParameterValuesByExpression<T>(Expression<Func<T>> parametrizedMethodCall)<br /> {<br /> <span class="rem">// We need to create lambda expression based on specified method call expression</span><br /> <span class="rem">// But replace in it MethodCall with another method retrieving parameter values, keeping the same arguments</span><br /><br /> var args = ((MethodCallExpression)parametrizedMethodCall.Body).Arguments.Select(arg => Expression.Convert(arg, <span class="kwrd">typeof</span>(<span class="kwrd">object</span>))).ToArray();<br /> <span class="rem">// All arguments must be boxed for GetParameterValues operation, otherwise runtime exception</span><br /><br /> Func<<span class="kwrd">object</span>[], <span class="kwrd">object</span>[]> getParamValuesDelegate = GetParameterValues;<br /> var getMethodCallParameterValuesExpression = Expression.Lambda<Func<<span class="kwrd">object</span>[]>>(<br /> Expression.Call(getParamValuesDelegate.Method, Expression.NewArrayInit(<span class="kwrd">typeof</span>(<span class="kwrd">object</span>), args))<br /> );<br /> <span class="rem">//Create expression replacing method call with a GetParameterValues</span><br /><br /> var getMethodCallParameterValues = getMethodCallParameterValuesExpression.Compile(); <br /> <span class="kwrd">return</span> getMethodCallParameterValues();<br /> }<br /><br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Calculates uniq key for particular method-call lambda expressions</span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <typeparam name="T"></typeparam></span><br /> <span class="rem">/// <param name="parametrizedMethodCall"></param></span><br /> <span class="rem">/// <returns></returns></span><br /> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">string</span> GetFunctionCacheKey<T>(Expression<Func<T>> parametrizedMethodCall)<br /> {<br /> var parameterValues = GetParameterValuesByExpression(parametrizedMethodCall);<br /> var hc = parameterValues.GetHashCodeOfSerializableContent();<br /> var fMethod = ((MethodCallExpression)parametrizedMethodCall.Body);<br /> var fullMethodName = fMethod.Method.DeclaringType.FullName + <span class="str">"."</span> + fMethod.Method.Name;<br /> var cacheKey = fullMethodName + hc.ToString();<br /> <span class="kwrd">return</span> cacheKey;<br /> }<br /><br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Removes cache of this particular operation</span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <typeparam name="T"></typeparam></span><br /> <span class="rem">/// <param name="parametrizedMethodCall">Method call Lambda expression. Like "()=>GetSomeLongExecutedFunction(par1,par2,"par3",...)"</param></span><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> Invalidate<T>(Expression<Func<T>> parametrizedMethodCall)<br /> {<br /> RemoveFromCache(GetFunctionCacheKey(parametrizedMethodCall));<br /> }<br /><br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Try to get function result from Cache. If it was not cached yet, execute function, caches result and return it.</span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <typeparam name="T"></typeparam></span><br /> <span class="rem">/// <param name="parametrizedMethodCall">Method call Lambda expression. Like "()=>GetSomeLongExecutedFunction(par1,par2,"par3",...)"</param></span><br /> <span class="rem">/// <returns></returns></span><br /> <span class="kwrd">public</span> T Get<T>(Expression<Func<T>> parametrizedMethodCall)<br /> {<br /><br /> var cacheKey = GetFunctionCacheKey(parametrizedMethodCall);<br /> <span class="kwrd">object</span> result = <span class="kwrd">null</span>;<br /> <span class="kwrd">if</span> (TryGetFromCache(cacheKey, <span class="kwrd">out</span> result))<br /> <span class="kwrd">return</span> (T)result;<br /><br /> var func = parametrizedMethodCall.Compile();<br /> result = func();<br /> StoreToCache(cacheKey,result);<br /><br /> <span class="kwrd">return</span> (T)result;<br /> }<br /><br /><br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Default cache storage</span><br /> <span class="rem">/// </summary></span><br /> Dictionary<<span class="kwrd">string</span>, <span class="kwrd">object</span>> cacheDictionary = <span class="kwrd">new</span> Dictionary<<span class="kwrd">string</span>, <span class="kwrd">object</span>>();<br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Retrieves information from CacheStorage</span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <param name="cacheKey"></param></span><br /> <span class="rem">/// <param name="result"></param></span><br /> <span class="rem">/// <returns></returns></span><br /> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">bool</span> TryGetFromCache(<span class="kwrd">string</span> cacheKey, <span class="kwrd">out</span> <span class="kwrd">object</span> result)<br /> {<br /> <span class="kwrd">return</span> cacheDictionary.TryGetValue(cacheKey,<span class="kwrd">out</span> result);<br /> }<br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Store object to Cache Storage</span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <param name="cacheKey"></param></span><br /> <span class="rem">/// <param name="objectToCache"></param></span><br /> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> StoreToCache(<span class="kwrd">string</span> cacheKey, <span class="kwrd">object</span> objectToCache)<br /> {<br /> cacheDictionary[cacheKey] = objectToCache;<br /> }<br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Removes record from cache storage for particular key</span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <param name="cacheKey"></param></span><br /> <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> RemoveFromCache(<span class="kwrd">string</span> cacheKey)<br /> {<br /> cacheDictionary.Remove(cacheKey);<br /> }<br /><br /> }<br />}<br /></pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /><br /><p> </p><br /><hr><br /><br /><p> </p><br /><p>And here is the example how it’s gonna be used in “consumer’s” code:</p><br /><hr><br /><pre class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Linq;<br /><span class="kwrd">using</span> System.Threading;<br /><br /><span class="kwrd">namespace</span> PMunin.com<br />{<br /><br /> <span class="kwrd">class</span> Program<br /> {<br /><br /><br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Some long running operation (like getting things from Database or WebServices)</span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <param name="ctr"></param></span><br /> <span class="rem">/// <returns></returns></span><br /> <span class="kwrd">static</span> <span class="kwrd">string</span> LongRunningDataCall(MyContainerObject ctr, <span class="kwrd">int</span> i)<br /> {<br /> Thread.Sleep(1000);<br /> <span class="rem">//returns first item.Str, or "empty"</span><br /> <span class="kwrd">return</span> (ctr.ItemsInContainer.FirstOrDefault() ?? <span class="kwrd">new</span> MyItemInContainer() { Str=<span class="str">"empty"</span>}).Str;<br /> }<br /><br /><br /> <span class="kwrd">static</span> <span class="kwrd">void</span> Main(<span class="kwrd">string</span>[] args)<br /> {<br /> Cache cache = <span class="kwrd">new</span> Cache();<br /><br /> MyItemInContainer subObject;<br /> var ctr = <span class="kwrd">new</span> MyContainerObject()<br /> {<br /> ItemsInContainer = <span class="kwrd">new</span> []<br /> {<br /> (subObject = <span class="kwrd">new</span> MyItemInContainer(){Str=<span class="str">"Item1"</span>})<br /> }<br /> };<br /><br /> <span class="rem">//This is first execution with this combination of input parameters. LongRunningDataCall will be executed</span><br /> var res = cache.Get(() => LongRunningDataCall(ctr, 1));<br /> <span class="rem">//now cache has ({Str"Item1",Int=0}, 1)</span><br /><br /> <span class="rem">//This inp. parameters combination is already in cache. LongRunningDataCall is not executed here</span><br /> var res2 = cache.Get(() => LongRunningDataCall(ctr, 1)); <br /><br /> subObject.Int = 25; <span class="rem">//Changing sub the object of </span><br /><br /> <span class="rem">//Argument changed - will execute BackendLongOperation</span><br /> res = cache.Get(() => LongRunningDataCall(ctr, 1)); <br /> <span class="rem">//now cache has </span><br /> <span class="rem">// ({Str"Item1",Int=0}, 1)</span><br /> <span class="rem">// ({Str"Item1",Int=25}, 1)</span><br /><br /><br /> <span class="rem">//Complicated lambda expression works as well!</span><br /> res = cache.Get(() => LongRunningDataCall(<br /> <span class="kwrd">new</span> MyContainerObject()<br /> {<br /> ItemsInContainer = <span class="kwrd">new</span> MyItemInContainer[]<br /> {<br /> <span class="kwrd">new</span> MyItemInContainer(){Str=myContextVariable} <span class="rem">//myContextVariable=="Item1", which is already in cache</span><br /> }<br /> },1<br /> )); <span class="rem">//This input parameter is already in cache will take it from there, without executing target operation</span><br /><br /> }<br /><br /> <span class="kwrd">static</span> <span class="kwrd">string</span> myContextVariable = <span class="str">"Item1"</span>;<br /> }<br /><br /> <br /> [Serializable]<br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MyContainerObject<br /> {<br /> <span class="kwrd">public</span> MyItemInContainer[] ItemsInContainer { get; set; }<br /> }<br /><br /> [Serializable]<br /> <span class="kwrd">public</span> <span class="kwrd">class</span> MyItemInContainer<br /> {<br /> <span class="kwrd">public</span> <span class="kwrd">string</span> Str { get; set; }<br /> <span class="kwrd">public</span> <span class="kwrd">int</span> Int { get; set; }<br /> }<br />}<br /></pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /><br /><hr><br /><br /><p>Possible issues and limitations:</p><br /><p>- I assume using reflection and LambdaExpression.Compile() may meet some security limitations in not FullTrust enviroments. However I didn’t verify it out.</p><br /><p>- Objects for input parameters must be serializable to estimate hash code properly</p><br /><p> </p><br /><p>Please let me know if you see any other issues.</p><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style> Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-52712264788177729652011-08-23T20:09:00.003-04:002011-08-23T23:06:15.251-04:00GetHashCode for serializable object extention<p>The following code demonstrates how to implement HashCode computation based on uniqueness content of abstract object. You can pass an object graph which will estimate HashCode based on member values:<pre class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.IO;<br /><span class="kwrd">using</span> System.Linq;<br /><span class="kwrd">using</span> System.Runtime.Serialization.Formatters.Binary;<br /><span class="kwrd">using</span> System.Text;<br /> <br /><span class="kwrd">namespace</span> PMunin.com<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> GetHashCodeExtension<br /> {<br /> <span class="rem">/// <summary></span><br /> <span class="rem">/// Retrieves HashCode of serializable object, based on serializing object to bytes, converting bytes to string and returning its hashcode</span><br /> <span class="rem">/// </summary></span><br /> <span class="rem">/// <param name="serializableObject"></param></span><br /> <span class="rem">/// <returns></returns></span><br /> <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">int</span> GetHashCodeOfSerializableContent(<span class="kwrd">this</span> <span class="kwrd">object</span> serializableObject)<br /> {<br /> var formatter = <span class="kwrd">new</span> BinaryFormatter();<br /> <span class="kwrd">using</span> (var ms = <span class="kwrd">new</span> MemoryStream())<br /> {<br /> formatter.Serialize(ms, serializableObject);<br /> var resStr = Convert.ToBase64String(ms.ToArray());<br /> <span class="kwrd">return</span> resStr.GetHashCode();<br /> }<br /> }<br /> <br /> }<br />}<br /><br /></pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style> Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-27171934006818800612011-01-16T15:28:00.001-05:002011-01-16T15:28:41.560-05:00Homepage website integration with Blogspot<p>I’ve changed design of the homepage. Now it is fully integrated with blogspot. This means that I can change layout and theme on my blogspot and changes will affect my main site immediately.</p> <p>Actually it is an experimental step. MasterPage now is created dynamically by downloading blogspot landing page and replacing appropiate sections with ContentPlaceHolder. Result stored in database and attached by custom VIrtualPathProvider.</p> <p>It appeared that BlogSpot pages overloaded by embedded stylesheets. So there is some optimization work remains. Anyway homepage and blog look consistent now.</p> Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-31187979167400258842011-01-05T21:49:00.001-05:002011-01-05T21:54:27.720-05:00.NET Random Mock<p>I published my first open-source project to codeplex. You can find it here: <a href="http://randomMock.codeplex.com">http://randomMock.codeplex.com</a></p> <p><a href="http://randomMock.codeplex.com" target="_blank"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWgsmOWEqpvrwVlgEvEJ4MI7HpSeD7IEP7GK0tNY9GPbMjwj_hCCN9wVLKZ3IqyeUTny4rLUow5qNcTcb-rMQ0FeMYMa3gDmdJN3wH-ahqk1Eu1QNg97v1QuYm73chbwtY3Tfpe3Mbwfax/?imgmax=800" width="481" height="400"></a></p> <p>This is Moq extensions that allow you to implement any object models and populate it with a random data by one line of code. You can see the link for more details. </p> <p>I am a worshipper of MVVM pattern (its modification). I used it for a long time before I got to know that this is called MVVM. So the first real world implementation of this extension for me is generating test ViewModels for Views. Currently I’m working on project based on ASP.NET MVC and I’m injecting MVVM pattern to it, as views are too complicated to use domain object model directly.</p> Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-65062742516206336152010-12-30T22:45:00.000-05:002011-01-05T22:45:58.489-05:00Upgrade of Laptop HP Pavilion tx2500<p>Just to let know the guys like me that official documentation and consultants in computer stores lie :)</p> <p>They all say that the laptop supports only up to 4GB of RAM as a total maximum (up to 2GB per slot). Anyway this is bullshit.</p> <p>Also you can find in internet that you laptop is not compatible with SATA II and supports up to 320GB hard-drives. At least consultant will try to make you sure that 750GB hard disk is too large for your laptop and it will not fit it by dimensions, he will say that maximum you can try is 640GB. Well probably I was just lucky to find a compact 750GB hard drive by Seagate that has the same height as my old 160GB hard disk.</p> <p>Anyway I have successfully upgraded my HP Pavilion tx2500 2GB RAM, 160GB 5200 RPM to 8GB RAM (Corsair PC6400), 750GB (Seagate ST9750420AS 7200 RPM).</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvGYRSvE5M06kWCRrgogDWuTAalzH0UAXhLdLCyTkepsc08skL-7ZiViG40yy7BtuF6c8-1hKGoYvyvX_bAZd3V-5OkSsMMYUbSlCiZFKIf-loIV-ZV8AnncbvbXXX6N6NUp4MJ3lXd8KT/s1600-h/image%5B5%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO6_KnabBjtIFnVdXqTBl2mpK57sTmc8g_0Eg-YVfI4TohuE32V59VMEB_-7CJhsk7wE_89xFqO8qTCxQqnGwUPL0-7q6bXATfyhvgGnP49G7WyYYVp7w7NgWk6gYybyF1bWDIeL8yz3lV/?imgmax=800" width="519" height="330"></a></p> <p>I was worried about the warming of large and fast hard drive but it warms not worse than the small did.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgenDtzs-8Ebt4x770U2lSmCeSU8Y8XIofZiKlrSzVOjg309HuDuQUgOulTrpBrYx6GI1U2eXcOIgSqOwnKhNqho1oGGm5Mn0UNWGwMdJuf2lvRO94DD1mBAy2qk8tNbprNq0NvwB5VXy1S/s1600-h/image%5B9%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKjBR5vD7PzMAQ-QwmPsK_3z_Ukxykj8edmPK_cd6ndiYLim13e0qEtVJ4SseS1xGWU-Z5WDYvo4eFJk_aFsjduPiJGU0jMH93XIjCaFEAeffrnUI2jI2updBDNdHT84Fu8GyIs7JVNQGS/?imgmax=800" width="420" height="141"></a></p> <p>Now my laptop works really fast. No hanging up for 10 seconds opening “My computer”. I’m really happy with this upgrade.</p> Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.comtag:blogger.com,1999:blog-4751188883414919379.post-31484850937620584382010-09-29T11:33:00.002-04:002010-11-20T22:00:17.578-05:00WelcomeHi there, <br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgprdtVuUkhm1cMjUdx258716cdkn9kj9YAmJV6CPr0ceG_G4RYSMkJ3b65mzl2a83bvzIG8M7nHLZNAcdtC6Pg08SYHG4xx2aVpMu2dcRyRwxytwyO8yp6hxcoUc_L4YvNh0RTnfh14lua/s1600-h/OntarioFlag%5B2%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="OntarioFlag" border="0" alt="OntarioFlag" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc7PZNAlF-JTAUyCXCWZgPvXcoDkhUQLAQFGltlhAKJasx3EhyYuZ5IWakFJIfAs49QvGcit0QaQ4d79v-e2XHDM967WdTQYkYhx__Khu9gDcRu7KpWYhSh56FW4zuUX9bUX43ifzp4gHc/?imgmax=800" width="244" height="124" /></a> <br />This is my first record in a blog, which is a part of my homepage http://pmunin.com. I will try to describe here all things and thoughts. <br /> <br />Temporary: Right now my homepage is not finished. It requires some work with stylesheets, which hopefully will be done soon. <br /> <br />Thanks for comming. Philipp Muninhttp://www.blogger.com/profile/16056660563751203613noreply@blogger.com