Find all "(?>!(CONSTRAINT|--) .*)FOREIGN KEY", Regular expressions, Subfolders, Find Results 1, Current Project: Project.Sql\Project.Sql.sqlproj, "*.SQL"
Monday, April 14, 2014
VS2013 negative look-behind on a sql server database project
Wednesday, March 12, 2014
Vs2013 search and replace in html classes
class="\s*(\w+)\s+(\s\w+)?\s*"
replace:
class="$1$2"
It only handles up to 2 classes being inside and... I forgot to consider the possibility of having razor inside.
However, this shouldn't break that it just won't clean it.
Monday, January 20, 2014
T4 Generating Dummy Adapters
I needed to code up an adapter layer between the domain and the ui. For now, and until something more specific is needed, just expose out the public methods of the domain and their result types. There is more that the adapter is encapsulating but the premise remains.
Added my Nuget packages for code generation: T4EnvDte and T4MultiFile.
As it turns out some of the code that was useful for this operation required a modification of T4EnvDte. So I added an assembly reference to EnvDTE80. This was to finally write usable code to get all the projects in a solution recursing through solution folders.
Let's have a look at the actual T4 line by line, that uses the new code so we can see what is required for this task.<#@ template debug="True" language="C#" hostspecific="True" #> <#@ output extension=".txt"#> <#@ include file="MultipleOutputHelper.ttinclude" #> <#@ import namespace="EnvDTE"#> <# EnvDTE.DTE Dte; #> <#@ include file="EnvDteHelper.ttinclude" #> <# bool doMultiFile=true;#>
This is the basic start of the file, with 2 variables declared thus far. Dte and doMultiFile. One is the Visual studio com object, the other is a flag telling T4MultiFile if we want to generated multiple files or all into one.
Main file output Last run at <#=DateTime.UtcNow.ToString()#>
This simple code is all that is going to the main file output, a simple date/time string for showing when the file was last run. The usefulness is debatable in any proper source controlled scenario.
<# var manager = Manager.Create(Host, GenerationEnvironment);
var targetNs=System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint"); //1
var projects= RecurseSolutionProjects(Dte); //2
var project = projects.First(p=>p.Name=="Company.Domain"); //3
var toGen= RecurseProjectItems(project).Where(pi=>pi.Name.StartsWith("Org")); //4
foreach(var p in toGen){
var className=Before(p.Name,".")+"Adapter"; //1
manager.StartNewFile(className+".generated.cs"); //2
var fcModel= p.FileCodeModel; //3
var ns=fcModel.CodeElements.OfType<EnvDTE.CodeNamespace>().First(); //4
var codeClass= ns.Children.OfType<EnvDTE.CodeClass>().First(); //5
var codeMethods= codeClass.Children.OfType<EnvDTE.CodeFunction>(); //6
#>
This is all the setup and starting the file per type looping.
targetNsasks what the proper namespace for our current file output location would beprojectsgets all the projects in the current solution using the new EnvDte helper codeprojectthe actual project name we are looking fortoGengets the projectItems in the sourceprojectwe are interested in
classNameholds the name of the new adapter class- tell the helper to start a new file for the class
fcModelholds the FileCodeModel of the current source projectItemnsholds the namespace that wraps our target class and assumes there is only one namespace in the source filecodeClassholds the reference to the target class and assumes there is only one class in the source filecodeMethodsgets all the methods of the source class
the meat of the individual file generation
//<#=p.Name#> <# /* 1 */ #>
using <#= ns.Name#>; <# /* 2 */ #>
namespace <#=targetNs#>{ <# /* 3 */ #>
public class <#=className#>{ <# /* 4 */ #>
<# foreach (var m in codeMethods.Where(m=>m.Access==EnvDTE.vsCMAccess.vsCMAccessPublic)){ var parms= m.Parameters.OfType<CodeParameter>(); #> <# /* 5-5.1 */ #>
public <#= m.Type.AsFullName#> <#=m.Name#>(<#=parms.Any()? parms.Select(parm=>parm.Type.AsString+" "+parm.Name).Aggregate((s1,s2)=>s1+","+s2):string.Empty#>){ <# /* 5.2 */ #>
return <#=Before(p.Name,".")#>.Instance.<#=m.Name#>(<#=parms.Any()?parms.Select(parm=>parm.Name).Aggregate((s1,s2)=>s1+","+s2):string.Empty#>); <# /* 5.3 */ #>
}
<# } #>
}
}
<#
manager.EndBlock();
} //end foreach
- adds a comment of the source file name
- adds a using clause for the source file's namespace
- adds a namespace for our new file
- adds a class to our new adapter
- loop over the public methods in the class
parmsholds a reference to the parameters of the method if any- Generate the method signature
- Generate the method return code (which includes the singleton-based
Instanceproperty requirement of this domain layer
- close up the single file generator and the foreach
the last little bits of code that complete the file
manager.Process(doMultiFile);
#>
<#+
string Before(string text, string delimiter)
{
return text.Substring(0,text.IndexOf(delimiter,StringComparison.CurrentCulture));
}
#>
So there we see using T4EnvDte and T4MultiFile together to generate specific classes from another project in the solution. I welcome any and all questions or suggestions for improvement
Tuesday, December 10, 2013
A little JQuery <-> Json <-> Mvc
It has been quite awhile since I've dealt with complex model binding across a set of inputs in mvc.
If one controller action's params (or a property on one of those params) is an IEnumerable<T> then Mvc will not write the element names in a way that will properly go back to the server.
I Json serialized the parent model into an html attribute on to some parent of the value(s) I want to submit. Some questions allow many answers, and I want to save each time a question answer is changed.
I'm working on making that serialization not contain the about to be consumedIEnumerable<T>property.
var save = function (element, value, event, previousValue,debug) {
console.log('saving:' + value + ' to ' + saveUrl);
var demoText = $(element).closest('[data-demographic]').attr('data-demographic');
var demoJson = htmlDecode(demoText);
var demoModel = JSON.parse(demoJson);
var oldAnswers = demoModel.PossibleAnswers;
demoModel.PossibleAnswers = [];
//TODO: handle multi-select, single-select radio, etc...
if (Object.prototype.toString.call(value) === '[object Array]') {
//value and previousValue could be arrays for multi-select answers
$.each(value, function (i, e) {
demoModel.PossibleAnswers.push({ Id: e });
});
} else {
demoModel.PossibleAnswers.push({ Id: value,Text:$(element).parent().text().trim() });
}
var data = JSON.stringify(demoModel);
data=data.replace('][', '].[');
$.ajax({
dataType: 'json',
url: saveUrl,
contentType: 'application/json; charset=utf-8',
accept: debug ? {
json: 'application/json',
} : {},
type: 'POST', data: data,
success: function (data, status, jqXhr) {
if (debug) {
var answerMirror = data.PossibleAnswers;
delete data.PossibleAnswers;
console.log(data);
console.log(answerMirror);
} else { //update dom to new read-only model?
//TODO: adjust with new html
console.log(data);
}
}
});
};
There's the heart of it. Notice I don't actually have to use the special name=foo.bar[0].Id on my inputs, but that is probably still a good idea.
This thing was almost working without doing any JSON.stringify but the IEnumerable<T> data was ignored by Mvc's model binder. With that in mind, I had to specify the contentType of the ajax request.
Wednesday, December 4, 2013
Inline markup delegates and razor helper delegate wars
This is mostly boilerplate bootstrap paneling, with masonry on top.
How would you provide a generic razor to meet bootstrap/masonry without creating a bunch of classes or partials to account for special case(s)? How in razor would you write a method that can take inline markup (for example any @<text> call)?
One way is
@helper Take note that HelperResult's documentation says specifically it is not intended to be used directly in your code.
So I headed in down the path of inline razor helper delegates:
