Spark learns a few new tricks
geek, internet, monorail, opensource, programming, spark, tech June 17th, 2008The folks at the Castle Project development list have provided some excellent constructive criticism and some new functionality was added to Spark as a result.
One thing which is new is the ability to inline code directly.
#int total = 0;
#foreach(var item in items)
#{
# total += item.Quantity;
#}
#if (Params["page"] == "2") {
<p>Second Page - total: $total;</p>
#} else {
<p>Not the second page
#}
Or using the slightly more standard <% %> syntax
<%
int total = 0;
foreach(var item in items)
{
total += item.Quantity;
}
%>
<%if (Params["page"] == "2") {%>
<p>Second Page - total: <%=total%> </p>
<% } else { %>
<p>Not the second page
<% } %>
Another question which came up was about the support for MonoRail ViewComponent classes. This was an especially interesting point because the view engine itself is written to be used in any framework, while the ViewComponent is very specific to the Castle Project. To make this happen the Spark parser and code generator was changed to call an extension factory interface as it processed the elements from the view templates it digested. This enabled the MonoRail-specific view engine library to recognize elements whose names matched those of the registered view components. It can then provide an extension that consume the contents of that element to write it’s own chunks of generated code at the appropriate point.
So the net result is support for things like this.
<p>blah blah blah</p> <DiggStylePagination Page="SomeMessages" Adjacents="3"> <prev>Go Back</prev> <next>Show More</next> </DiggStylePagination> <p>blah blah blah</p>
And another piece of functionality which was added was the ability to declare and use helper-like functions inside the template file.
<macro name="MessageBox" caption="string" message="string">
#Logger.Info(message);
<div class="msgbox">
<h3>$H(caption);</h3>
<div>$message;<div>
</div>
</macro>
<p>blah blah blah</p>
$MessageBox("Warning",
"You're about to change " + somearg + " permanently.");
<p>blah blah blah</p>
The thing that I think is pretty cool about that is how it create a function what works like a helper method, because it takes a handful of arguments and returns a string, but the body of this thing is declared in the template vernacular. So it can be very “view oriented” in how it’s build and maintained. Which makes sense for a lot of helper-style methods which are very much about the idea of concatinating and returning html - implementing simple helper methods in classes can occastionally put more html in your cs files than you’re comfortable with.
In any case I’m really happy with how the view engine has come together. It’s been a delightful experience, didn’t take much actual time, and has really reinforced for me the value of tools like resharper and practices like test driven development.
June 20th, 2008 at 5:32 pm
I’m really impressed with how much you’ve done wrt this topic. I’m just going to brain dump now as I’ve not found a whole lot of interest around the net, it appears many people are content to have code constructs interspersed among their ui markup.
I’ve been looking at ways of avoiding all over my code and while I know that the declarative constructs proposed for loops/if etc are just a bit of sugar over the top of the same logical context switches they just feel much better.
For the last few days I’ve been scratching my head trying to get a start on this topic. I’d got as far as extending the ie6 schemas and getting vs to pick up if/else/loop tags but what I really wanted was custom tags for reusable view elements, as the schemas are only parsed on vs startup I couldn’t see a way to extend the integrated designer to cope with custom tags.
One other thing I’d got to thinking about was that ideally I wanted two different types of sub-views, now please forgive me if these concepts are well understood by brighter people than I but I imagined:
1) vanilla sub-views tags (date control, phone number, paging). Equivalent of RenderUserControl helper method.
2) sub-views tags that kick of a chain of events more akin to controller interaction, except with a defined entry point that would propbably take a more complex object (customer, order) and select an appropriate sub-view. Equivalent of RenderComponent helper method.
I wasn’t really sure about the best way to differentiate between the two using a pure tag syntax and wondered if it is a topic you’ve given any thought to.
While I’m on a roll (I bet you give up reading this mess long ago) I noticed that your files use the extension xml, this lead me to think you do you do any compilation of the view or is it parsed. I only ask because I know that one of the things I liked least about nvelocity was the occasional runtime error due to misspelling a property name. I imagine intellisense is probably the last thing on your mind right now and as such wondered if you had give any thought to perhaps a custom extension and a buildprovider that could pre-parse the view and reflect over property names or use the code-dom to try and compile the code sections to give compile-time feedback to the dev.
Also on a final not I pcked up a comment you made about your if/else syntax. The syntax I had settled on was:
This
That
The other
Anyway loving your work and I’ll be following with interest
June 20th, 2008 at 5:37 pm
Sorry for the spelling/grammar, it’s late :-)
the last section of my comment didn’t publish correctly.
<if condition=’this’>
This
<elseif condition=’that’/>
That
<else/>
The other
</if>
June 20th, 2008 at 5:46 pm
Me again, don’t worry you haven’t got a stalker :-) I’ve only just seen the Spark link at the top which answers my compiled view question. Nice work
June 26th, 2008 at 11:28 pm
Sorry I didn’t see your comments for seven days! What horrible turn-around. I’m really due to put up another post on the subject.
One reason for that is I’m immersed in a real-world application of spark in some concept work at my day job.
Also a recent changes was to use a spark extension instead of an xml extension. It really should have been done from the beginning, because something you’ll see on monorail apps is a web.config element that denies access to all .vm files. Prevents downloading source… So having .xml as the source extension would be a problem if you have static .xml files.
That said you can associate .spark with the default xml editor in visual studio and still get the benefits of automatic element matching and indentation.
Intellisense is one of the things some colleagues which have missed the most when they’ve used velocity. It’s a very tricky thing to implement though. I have created a “visual studio integration package” project which provides colorization of the spark file - and it uses the view parser itself so it’s a perfect fit for the various types of markup and syntax.
The downside is all of the other xml editor magic goes away… The element auto-closing, the indentation and “reformat” beautifying, the warnings when elements aren’t matched. Plus you’re still left with the task of breaking down the csharp itself and providing intellisense data back up to the editor.
So a full-blown visual studio editor would be a pretty big effort. It left me even more amazed at what the folks who made resharper have accomplished.
June 27th, 2008 at 12:09 am
Thanks, by the way!
Another thing that’s changed is the [elseif condition='expr'] has become [else if='expr'].
I like what you’ve proposed for the conditional elements… The parsing could be One of the things I’ve also been looking for is some element name that could be used instead of [if condition='expr']
Like
[case if='this']
this
[else if='that'/]
that
[else/]
the other
[/case]
But none of the small, easily typed words that come to mind feel quite right.
July 1st, 2008 at 3:33 pm
Thanks for the update. I’m liking the <case> syntax it reads nicely and is much easier than conditional= on the fingers.
Using the editor association buys you a lot for no effort so is a really good start.
Having pondered over your syntax, I was wondering if a contained language might be any use for you in your VSIP, in much the same way as the standard ASP.net editor parses html (or in your case spark xml) and uses a seperate parser for the contained snippets of c#/vb.net which get their own colorization, intellisense etc
A link to what I mean is here:
http://msdn.microsoft.com/en-us/library/bb166334(VS.80).aspx
The article indicates that the primary buffer (i.e. the outer language coordinates the content that is passed for the second language to parse. If you enforced the use of ; as a terminator (I did pick that up right I hope) then what I have read seems to indicate that the primary language (your spark xml parser) could use the $ .. ; block as a context switch and hand off its contents to the c# language service to handle the colouring and intellisense. I’m guessing you’d have to revert back to angle brackets rather that in the code.
Sorry if all this is a red herring and I’m sure you probably have too much on your plate already. I’m the first to admit I know nothing on the topic of VSIP other than a bit of reading up so all this may be a case of a little knowledge is a dangerous thing.
P.S.
I’m also guessing you’ve seen the NVelocity VSIP project but have included the link for reference just in case: http://using.castleproject.org/display/Contrib/Castle+Visual+Studio+Integration
July 6th, 2008 at 11:51 pm
Sorry your comment didn’t appear right away - for some reason WordPress had flagged it as spam. I’m glad I looked in that queue.
That link about contained languages does look very promising! I was under the assumption I would need to parse the csharp as well to colorize, or possibly try to instantiate the csharp language colorizer and provide enough of a fake host environment to trick it into performing the answers to return. Which seemed like it would be tricky and a lot of effort. I’m glad to see the vs interfaces are built to support that type of embedding formally.
All of the csharp ranges within spark can be picked out by the language parser on the outside and it can use a variety of delimiters. For example $expr; ${expr} and < %=expr%> are all interchangeable so it should be possible to pass all the expr coord to the inner language service regardless of the delimiter used.
I wonder if the outer language needs to also provide the surrounding generated code as well. In aspx for example the fact that the code fragments appear inside a class descended from a particular base, and which using namespaces are in effect, would greatly affect what code is valid and what intellisense would appear.
I think I’ll take a look at that at some point but like you say there always seems to be something else to do first. I do have to say I still wish that Visual Studio Integration was done with managed classes instead of com interfaces. The support for implementing com interfaces isn’t bad. It just never feels as native or as intuitive.
I have seen the NVelocity project and it was helpful, but I’ve been relying even more on the iron python language service example from the SDK.
Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Samples\IronPythonIntegration
December 14th, 2008 at 5:31 am
[...] an earlier post there was a comment from Pablo Blamirez that provided a really interesting lead with a few of the contained language interfaces. Then [...]
February 3rd, 2009 at 1:47 am
can you please send me the advantages of using this veiwengines(Nvelocity,webforms,brail) in monorail is ther e any diffrences between them is this view engines are really worth full of developing a webform?is it better performer compare to others?
February 23rd, 2010 at 10:41 pm
Good day, I saw your weblog on Google Weblogs and believe it is actually pretty useful and provides fantastic subject matter. Many thanks regarding the great post, I may promote this on Twitter. Have a good day.