Spark for MR3

51 views
Skip to first unread message

Tomek Pluskiewicz

unread,
Aug 14, 2011, 1:15:13 PM8/14/11
to castle-pro...@googlegroups.com
OK, so I've started experimenting with implementing Spark View Engine for MR3

Apart from the nested transitions, which I have found (an ugly) workaround for, I am struggling with two issues.

1. Layouts

In the example web project layouts are defined directly in views. As much as like this approach, I don't think it will be possible with Spark, due to the way it renders. However the BaseViewEngine#ResolveView method gets layout paths as parameter. Unfortunately F# is pretty obsure for me at the moment and I couldn't find where in code these layout names are resolved. Is this implemented already?

2. HtmlResult

This is F# and not MonoRail question. In my workaround for the Form.For functionality I needed implicit cast operator for HtmlResult. Are cast operators overloadable in F#? I couldn't find an answer on MSDN.

3. IoC container integration

Right, MEF is indeed awesome at framework level - agreed. But at application level I'd still prefer Windsor or Autofac. Having used implemented Windsor for your project could you give some more details on wiring it up with MR+++?

4. Implementation status

It seems that the ActionName and HttpMethod attributes haven't been implemented yet. Especially the second one interests me. How could I help?

Regards
Tomasz

hammett

unread,
Aug 14, 2011, 2:48:08 PM8/14/11
to castle-pro...@googlegroups.com
On Sun, Aug 14, 2011 at 10:15 AM, Tomek Pluskiewicz <ploo...@gmail.com> wrote:
> OK, so I've started experimenting with implementing Spark View Engine for
> MR3

Bravo :-)

> In the example web project layouts are defined directly in views. As much as
> like this approach, I don't think it will be possible with Spark, due to the
> way it renders. However the BaseViewEngine#ResolveView method gets layout
> paths as parameter. Unfortunately F# is pretty obsure for me at the moment
> and I couldn't find where in code these layout names are resolved. Is this
> implemented already?

So in previous design the view engine was also responsible for
implementing the "convention" for resolving the views/layouts. I
separated that since I dont think this responsibility should lie with
them.

Currently this is how it looks

ViewRequest -> IViewFolderLayout -> IViewEngine

A controller can "decide" to render a view. It creates a viewrequest,
which is handed to DefaultViewFolderLayout so it fills the possible
locations. The view engine then tries to load the view sources from
these locations. The ViewRendererService coordinates these steps.

> 2. HtmlResult
> This is F# and not MonoRail question. In my workaround for the Form.For
> functionality I needed implicit cast operator for HtmlResult. Are cast
> operators overloadable in F#? I couldn't find an answer on MSDN.

This is a good question. I'm not sure myself. Do you need to
implicitly cast HtmlResult to string?

> 3. IoC container integration
> Right, MEF is indeed awesome at framework level - agreed. But at application
> level I'd still prefer Windsor or Autofac. Having used implemented Windsor
> for your project could you give some more details on wiring it up with
> MR+++?

Two steps:

1 - Add a reference to Castle.MonoRail.Extension.Windsor.dll
2 - On your global.asax.cs

public class Global : System.Web.HttpApplication, IContainerAccessor
{
private static WindsorContainer container;

void Application_Start(object sender, EventArgs e)
{
// routes

container = new WindsorContainer(new XmlInterpreter());
container.Register(AllTypes.FromThisAssembly().
Where(t => t.Name.EndsWith("Controller")).
Configure(r =>
r.LifeStyle.Transient.Configuration().Named("\\" +
r.Implementation.Name)));

container.Register(AllTypes.FromThisAssembly().
Where(t => t.Name.EndsWith("Component")).
Configure(r =>
r.LifeStyle.Transient.Configuration().Named("viewcomponents\\" +
r.Implementation.Name)));

container.Register(AllTypes.FromThisAssembly().
Where(t => t.Name.EndsWith("Filter")).
Configure(c => c.LifeStyle.Transient));

}

public IWindsorContainer Container
{
get { return container; }
}

void Application_End(object sender, EventArgs e)
{
if (container != null) container.Dispose();
}
}


> 4. Implementation status
> It seems that the ActionName and HttpMethod attributes haven't been
> implemented yet. Especially the second one interests me. How could I help?

Get more acquainted with F# :-)
My idea is to make the action name be explicit about the verb it
supports. HttpMethod is more like a backward-compatible way to do
that.

Actions would have the following method accessibility:
Home | Get only
PostCreate | Action Create : Post only
PutUpdate | Action Update : Put only (but supporting the fake post
with _method = PUT)
DeleteRemove | Action Remove : Delete only (ditto)

That would make easier to support two methods with different semantics

Create and PostCreate are very explicit in their goals.

I'd guess you'd need the following to get this done

- test cases for MethodInfoActionDescriptor (see Mvc.Typed.Descriptor.fs)
- change the MethodInfoActionDescriptor to expose the action name
without the verb (if present), save the verb from the name or
attribute).
- Implement the MethodInfoActionDescriptor.SatisfyRequest

Bonus points:
- I'd love a test case for DefaultActionSelector
(Mvc.Typed.ProgModel.fs) too, to make sure it is correctly filtering
the available actions based on the result of SatisfyRequest
- maybe refactor PocoControllerExecutor moving the selection of action
candidates to DefaultActionSelector?


--
Cheers,
hammett
http://hammett.castleproject.org/

Tomek Pluskiewicz

unread,
Aug 15, 2011, 3:28:24 PM8/15/11
to castle-pro...@googlegroups.com
Regarding View Component sections in Spark.

Lambdas may tricky with Spark. Most of it's syntax get wrapped in an TextWriter#Write call. Even if it parses into a C#, at the moment complex anonymous methods will be tricky. I will be looking to resolve this issue with Spark's team.

Anyway I understand that the principle is to pass sections' content template to a property and then it would be resolved inside view component's view. Is that right?

Spark tries to get as much XML-like as possible and so, viewcomponents look similarilly to the below:

<SomeComponent SomeProperty="variable">
   <SomeSection>
       <td>
          ${item.Name}
       </td>
   </SomeSection>
</SomeComponent>

In the way MonoRail 1/2 view component sections were openly declared this was easy. With the new ways I guess some plumbing is inevitable ;)

Gauthier Segay

unread,
Aug 15, 2011, 5:54:07 PM8/15/11
to Castle Project Development List
I still haven't check the status of MR3 but I'm used to Spark/MR2 and
ViewComponents (which don't have sibling in MS MVC AFAIK)

Your message makes me wonder if there are changes in VC, but I guess
it's still the nice and plain ones we have in MR2. I've checked
Hammett's post regarding Blade and could definitely concure with you
Tomek that passing template parts as lambda's is not gonna be simply
transposable to Spark.

That is actually something I've been fighting with Spark, which is
passing parts of templates as expression and I admit I always had to
work around using more verbose.

Spark uses a macro system which are mere functions taking defined set
of parameters, but there is no way to pass macros as macros for say, I
didn't try to "reverse engineer" (looking at generated code or at
Spark source) what would be the actual delegate signature to make this
hack work; but my feeling is that this could be leveraged to wrap
those lambdas as "anonymous" Spark macros.

That "template nesting" ability definitely gives an edge to Blade (pun
not intended), and I'm looking forward so that this get's available in
other view engines as I'd like to stick with Spark which is really
nice in every other aspects.

I'm also curious if it could be baked in spark in a way which remains
agnostic to framework using it as view engine (could work with spark
standalone, MSMVC and MR2 as well), that would be great.

I guess the implementation detail discussion will probably move to
spark group but I'm trying to get the hold of the top level
implications.

Tomek, do you feel the "anonymous macro" idea and some way to declare
macro typed parameters to macros would be a good fit ?

I can also see two issues investigating that way:

* macro have scoping which avoid referencing anything else than
parameters, it doesn't work as a closure, I guess one reason is that
you can define macros outside of the scope to be used at different
places (Hammett, is this possible with Blade? can you define what you
pass to builder.TemplateFormBuilder outside of the call?)
* macro aren't supporting generic type parameters

That lambda syntax definitely gives an edge to Blade (pun not
intended), it will probably open nice possibilities to define view
parts that are generic and extensible without necessarily going with
view component or helpers (if MR3 viewengine infrastructure bakes the
concept of declaring those parametric templates as an abstraction
similar to the concept of VC), I have to grasp what's done with
current helpers a bit more to understand better if it could possibly
fit. That would give another edge to MR3 beside Blade.

hammett

unread,
Aug 15, 2011, 6:05:44 PM8/15/11
to castle-pro...@googlegroups.com
Just to be clear on the changes to VC between older MR and MR3:

- We (Henry and I) noticed that is fairly common to have VC with
"actions", especially when combined with ajax
- therefore VC in MR3 is a controller implementing a interface
IViewComponent, that defines the default action.
- layout wise, they should live in a viewcomponents folder.

The principle remains the same, though. Controllers are flat and
vertical, hence not composable. ViewComponents is the way to aggregate
content/logic within views.

> --
> You received this message because you are subscribed to the Google Groups "Castle Project Development List" group.
> To post to this group, send email to castle-pro...@googlegroups.com.
> To unsubscribe from this group, send email to castle-project-d...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/castle-project-devel?hl=en.

Henry Conceição

unread,
Aug 15, 2011, 6:14:00 PM8/15/11
to castle-pro...@googlegroups.com
Posting here what I said about sections on the users list:

It don't requires any special pumbling with blade or alikes. A property that receives a inline template will do the job: 

ViewComponent.Render<Foo>(vc => vc.SomeSection = @<td> @item.Name </ td>) 

And on your vc view you must invoke the property supplying the desired arguments. With the blade support for lambdas, the sky is the limit. 

It's important to note that this approach isn't restricted to blade (or razor) views. If you can declare a inline template function with your ve, you should be done. 


Cheers,
Henry Conceição

Gauthier Segay

unread,
Aug 15, 2011, 6:16:49 PM8/15/11
to Castle Project Development List
As I understand it, VC with actions sound like a nice way to pack what
I would have done with VC + dynamic action providers in MR2, which
incurs declaring the provider on controllers using the VC.

Is my understanding right?

if it's right, how are the actions made accessible through routing?

Henry Conceição

unread,
Aug 15, 2011, 6:25:46 PM8/15/11
to castle-pro...@googlegroups.com
Yep. Since the vc itself is a controller, the actions are accessible like any other controller. You just have to have a route for the vc area.

Cheers,
Henry Conceição

hammett

unread,
Aug 15, 2011, 6:26:02 PM8/15/11
to castle-pro...@googlegroups.com
Not sure I follow. For all (Http) effects, a VC is just a controller,
with its own name and actions.

Gauthier Segay

unread,
Aug 15, 2011, 7:52:08 PM8/15/11
to Castle Project Development List
Thanks Henry/Hammett, I get it, sounds convenient when it makes sense
to package those relevant actions related to VC behaviour next to "VC
instance" implementation.

Although it can get confusing if the VC has instance members which
would be technically accessible in action's code without those being
relevant, I would not deem that as being a "best practice" in most of
the case but as a convenience to VC authors so there are less elements
to take care of when incorporating those into applications.

Henry Conceição

unread,
Aug 15, 2011, 8:03:02 PM8/15/11
to castle-pro...@googlegroups.com
Yep, it's a thin line. But the result of not having some ui widget spread across multiple partials/views/controllers in different places is pretty nice imo.

Cheers,
Henry Conceição

Tomek Pluskiewicz

unread,
Aug 20, 2011, 5:19:28 PM8/20/11
to castle-pro...@googlegroups.com
On Sunday, August 14, 2011 8:48:08 PM UTC+2, hammett wrote:
On Sun, Aug 14, 2011 at 10:15 AM, Tomek Pluskiewicz <ploo...@gmail.com> wrote:
> OK, so I've started experimenting with implementing Spark View Engine for
> MR3

Bravo :-)

Hi

I've forked MR3 and there is some work done already implementing Spark for MonoRail 3.


Minor refactorings are still needed, especially in the way views are resolved. I'm still exploring the new API.
Other than that, basic views and simple components with just body work already. I am in progress of porting the test suite from Spark's existing Monorail library

I would love to hear some constructive criticism. 

Regards
Tomasz 

hammett

unread,
Aug 21, 2011, 2:16:15 AM8/21/11
to castle-pro...@googlegroups.com
how do I compare two repositories? should I merge and see the diff?

> --
> You received this message because you are subscribed to the Google Groups
> "Castle Project Development List" group.

> To view this discussion on the web visit
> https://groups.google.com/d/msg/castle-project-devel/-/tS2fpk1r7rIJ.


> To post to this group, send email to castle-pro...@googlegroups.com.
> To unsubscribe from this group, send email to
> castle-project-d...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/castle-project-devel?hl=en.
>

--
Cheers,
hammett
http://hammett.castleproject.org/

Kelly Leahy

unread,
Aug 21, 2011, 2:23:21 AM8/21/11
to castle-pro...@googlegroups.com
Hammett, if you fetch from one repo into yours, i.e. set up a remote (called "other" below) and do:
 
git fetch other <branchname>
 
(<branchname> is optional, if you don't supply it you'll get all of their branches)
 
Then, you can do a diff using:
 
git diff master other/master
 
if, for instance, you want to compare their master branch to yours.
 
In general, this command is:
 
git diff <branch> <remote>/<remotebranch>
 
as I've done it here.
 
In even more general terms, git diff takes two "commit names" in this usage.

hammett

unread,
Aug 21, 2011, 3:17:56 AM8/21/11
to castle-pro...@googlegroups.com
Cool thing! Thanks, Kelly!

hammett

unread,
Aug 21, 2011, 4:30:16 AM8/21/11
to castle-pro...@googlegroups.com
Did I mess something up?

$ git diff master other/master/
fatal: ambiguous argument 'other/master/': unknown revision or path not in the w
orking tree.
Use '--' to separate paths from revisions

$ git remote -v
origin g...@github.com:castleproject/Castle.MonoRail3.git (fetch)
origin g...@github.com:castleproject/Castle.MonoRail3.git (push)
other https://github.com/ploosqva/Castle.MonoRail3.git (fetch)
other https://github.com/ploosqva/Castle.MonoRail3.git (push)

Kelly Leahy

unread,
Aug 21, 2011, 4:31:34 AM8/21/11
to castle-pro...@googlegroups.com
you don't want that extra / at the end.
 
just git diff master other/master
 
Kelly

hammett

unread,
Aug 21, 2011, 4:45:02 AM8/21/11
to castle-pro...@googlegroups.com
Same error..

Kelly Leahy

unread,
Aug 21, 2011, 4:46:45 AM8/21/11
to castle-pro...@googlegroups.com
hmm...
 
what does "git branch -r" say?  also, what does "git branch" say?

hammett

unread,
Aug 21, 2011, 4:55:03 AM8/21/11
to castle-pro...@googlegroups.com
Here it goes

hammett@HAMMETT-LAPTOP /c/dev/github/castle/Castle.MonoRail3 (master)
$ git branch -r
origin/HEAD -> origin/master
origin/hammett_exp
origin/master
origin/viewcpnts
other/HEAD -> other/master

hammett@HAMMETT-LAPTOP /c/dev/github/castle/Castle.MonoRail3 (master)
$ git branch
* master

Kelly Leahy

unread,
Aug 21, 2011, 4:56:46 AM8/21/11
to castle-pro...@googlegroups.com
hmmm... other/HEAD looks like what you're looking for.  Not sure why there isn't an other/master listed in git branch -r.
 
Kelly

Kelly Leahy

unread,
Aug 21, 2011, 4:57:20 AM8/21/11
to castle-pro...@googlegroups.com
did you do a "git fetch other" yet?

hammett

unread,
Aug 21, 2011, 6:21:05 AM8/21/11
to castle-pro...@googlegroups.com
I did.

HEAD also didn't work.

$ git diff master other/HEAD
warning: ignoring dangling symref refs/remotes/other/HEAD.
warning: ignoring dangling symref refs/remotes/other/HEAD.
fatal: ambiguous argument 'other/HEAD': unknown revision or path not
in the working tree.


Use '--' to separate paths from revisions

Kelly Leahy

unread,
Aug 21, 2011, 6:27:57 AM8/21/11
to castle-pro...@googlegroups.com
it looks like the fetch doesn't seem to have worked.
you might want to just compare on github, I'm pretty sure you can do it there too via the web UI.
 
it could be that the way you have your remotes set up is funky...  I wonder if it has something to do with the https on the remotes.  I've never tried to use https on git.
 
how did you set up the remote?  did you just do:
 
git remote add other <url>
 
or did you do something else?
 
you might try git remote rm other, then
 
 
instead of the https stuff.

Tomek Pluskiewicz

unread,
Aug 21, 2011, 9:33:09 AM8/21/11
to castle-pro...@googlegroups.com
On Sunday, August 14, 2011 8:48:08 PM UTC+2, hammett wrote:
On Sun, Aug 14, 2011 at 10:15 AM, Tomek Pluskiewicz <ploo...@gmail.com> wrote:
> In the example web project layouts are defined directly in views. As much as

> like this approach, I don't think it will be possible with Spark, due to the
> way it renders. However the BaseViewEngine#ResolveView method gets layout
> paths as parameter. Unfortunately F# is pretty obsure for me at the moment
> and I couldn't find where in code these layout names are resolved. Is this
> implemented already?

So in previous design the view engine was also responsible for
implementing the "convention" for resolving the views/layouts. I
separated that since I dont think this responsibility should lie with
them.

Currently this is how it looks

  ViewRequest -> IViewFolderLayout -> IViewEngine

A controller can "decide" to render a view. It creates a viewrequest,
which is handed to DefaultViewFolderLayout so it fills the possible
locations. The view engine then tries to load the view sources from
these locations. The ViewRendererService coordinates these steps.

I'm not sure I follow. On ViewRequest there is just a single layout name. Not an array. That imposes a question. What do I do to pass multiple, nested layouts the way it was possible with MR2's LayoutsAttribute? Would I have to create a new IViewFolderLayout implementation? This seems quite heavy...

Also I'm not sure where is that ViewRequest really created. As I understand a Controller 'decides' which layout/view to render based on ViewResult#LayoutName and ViewResult#ViewName.

Another thing I find missing is the possibility to choose View/Layout on ContentNegotiatedResult. Otherwise how is is possible to choose layout and view when client requests html? It seems however that it will all become clear when I fully understand the ViewRequest.

> 2. HtmlResult
> This is F# and not MonoRail question. In my workaround for the Form.For
> functionality I needed implicit cast operator for HtmlResult. Are cast
> operators overloadable in F#? I couldn't find an answer on MSDN.

This is a good question. I'm not sure myself. Do you need to
implicitly cast HtmlResult to string?


I need the implicit cast temporarily until there is a better way to wrap up transitions with Spark. Verbose enough I just didn't want another ToString() call and I was surprised I couldn't find that implicit casting... For now I simply derived in C#. 

Mauricio Scheffer

unread,
Aug 21, 2011, 12:05:57 PM8/21/11
to castle-pro...@googlegroups.com
Note that g...@github.com:ploosqva/Castle.MonoRail3.git probably won't work for hammett as remote, since it's Tomas' private read+write URL to his repo. Instead, use the public, read-only URL: git://github.com/ploosqva/Castle.MonoRail3.git .

--
Mauricio

hammett

unread,
Aug 21, 2011, 4:35:19 PM8/21/11
to castle-pro...@googlegroups.com
That did it. Thanks

hammett

unread,
Aug 21, 2011, 4:50:08 PM8/21/11
to castle-pro...@googlegroups.com
On Sun, Aug 21, 2011 at 6:33 AM, Tomek Pluskiewicz <ploo...@gmail.com> wrote:
> I'm not sure I follow. On ViewRequest there is just a single layout name.
> Not an array. That imposes a question. What do I do to pass multiple, nested
> layouts the way it was possible with MR2's LayoutsAttribute?

Just change the signature on ViewRequest. Also change ViewResult and
variations.

> Also I'm not sure where is that ViewRequest really created.

I believe the implementation of ActionResults does.

> Another thing I find missing is the possibility to choose View/Layout on
> ContentNegotiatedResult. Otherwise how is is possible to choose layout and
> view when client requests html?

Actually it is possible, since you can customize the "action" for a
mime type. Something like

var result = new ContentNegotiatedResult(..);
result.When(MimeType.Html, () => new ViewResult(...));


> I need the implicit cast temporarily until there is a better way to wrap up
> transitions with Spark. Verbose enough I just didn't want another ToString()
> call and I was surprised I couldn't find that implicit casting... For now I
> simply derived in C#.

What's the signature in C#? I may try to translate it to f# here and test it...

hammett

unread,
Aug 22, 2011, 2:34:58 PM8/22/11
to castle-pro...@googlegroups.com
Sorry for being such a newbie.. but I'm trying to generate a concise
diff file with the changes. Running git diff master other/master is
opening winmerge for every single file, changed or not :-$

Thanks!

ser...@hosca.com

unread,
Aug 22, 2011, 2:52:01 PM8/22/11
to castle-pro...@googlegroups.com
It would be easier to look at individual commits.

First switch to ploosqva/master:
$ git checkout ploosqva/master

Then do format patch comparing to origin:
git format-patch origin

This should generate patch files for individual commits.

HTH

hammett

unread,
Aug 22, 2011, 2:55:09 PM8/22/11
to castle-pro...@googlegroups.com
Cool. Will it try it later today. Thanks!

Kelly Leahy

unread,
Aug 22, 2011, 2:56:44 PM8/22/11
to castle-pro...@googlegroups.com
It seems like you might have your default merge tool set up to do diffs instead of set up as your difftool.  I wouldn't recommend doing this (i.e. making git diff use winmerge).
 
If you want to send me your config file for git I can recommend how you should improve it - probably don't want to send it to the whole list, if you want to take this offline.
 
Kelly

hammett

unread,
Aug 22, 2011, 2:58:37 PM8/22/11
to castle-pro...@googlegroups.com
Would that be git config --global -l ?

Kelly Leahy

unread,
Aug 22, 2011, 3:01:02 PM8/22/11
to castle-pro...@googlegroups.com
git config --list will give you everything (from all config files).

hammett

unread,
Aug 22, 2011, 3:46:54 PM8/22/11
to castle-pro...@googlegroups.com
Here it goes:

$ git config --list
core.symlinks=false
core.autocrlf=false
color.diff=auto
pack.packsizelimit=2g
help.format=html
http.sslcainfo=/bin/curl-ca-bundle.crt
sendemail.smtpserver=/bin/msmtp.exe
user.name=hammett
user.email=ham...@gmail.com
gui.fontdiff=-family Consolas -size 11 -weight normal -slant roman
-underline 0 -overstrike 0
gui.recentrepo=C:/dev/personal/wp7/NprNews
diff.external=C:/dev/tools/WinMerge/git-diff-wrapper.sh
diff.tool=winmerge
merge.tool=diffmerge
mergetool.diffmerge.cmd=git-merger-wrapper.sh $PWD/$LOCAL $PWD/$BASE
$PWD/$REMOTE $PWD/$MERGED
mergetool.diffmerge.trustexitcode=false
mergetool.diffmerge.keepbackup=false
core.autocrlf=false
difftool.prompt=false

Kelly Leahy

unread,
Aug 22, 2011, 3:50:19 PM8/22/11
to castle-pro...@googlegroups.com
ok... I think it's "diff.external" that you shouldn't probably use
 
That should instead be in a mergtool and a difftool.  Then, when you use "git diff ..." you'll get the "native" git diff, and when you use "git difftool ..." you'll get your "special" diff tool.
 
a difftool is set up similar to the way you have the mergetool setup, except with less parameters.  I'm not sure what the cmdline should look like for winmerge, but I'm pretty sure you can find it on the net somewhere.
 
Kelly

Reply all
Reply to author
Forward
0 new messages