5

Call me crazy but I'm developing an ASP.NET MVC4 site in F#. Here's my first roadblock; in the controller I submit a dictionary, this way:

[<HandleError>]
type FooController() =
    inherit Controller()
    member this.Index () =
        this.ViewData.Add("Foo", "Bar")
        this.ViewData.Add("Baz", dict [ (0, 0); (1, 3); (2, 2); ] )
        this.View() :> ActionResult

Now I want to iterate through the values in the Razor template, how to do it? I've tried this:

@foreach (var time in @ViewBag.Baz.Keys)
{
    <hr /><p>Time is @time, and value is @ViewBag.Baz[time]</p>
}

But it throws this error:

Line 119:                    Total: <span class="highlight">6449</span> kW/h.
Line 120:                </p>
Line 121:                @foreach (var time in (@ViewBag.Baz).Keys)
Line 122:                {
Line 123:                    <hr /><p>Time is @time, and value is @ViewBag.Baz[time]</p>

[RuntimeBinderException: 'object' does not contain a definition for 'Keys']
   CallSite.Target(Closure , CallSite , Object ) +280
   System.Dynamic.UpdateDelegates.UpdateAndExecute1(CallSite site, T0 arg0) +924
   ASP._Page_Views_lobby_Index_cshtml.Execute() in c:\Users\knocte\documents\visual studio 2012\projects\fsolar\conclavesolarweb\conclavesolarwebwebapi\Views\Lobby\Index.cshtml:121
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +280
   System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +126
   System.Web.WebPages.StartPage.ExecutePageHierarchy() +143
   System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +181
   System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +378
   System.Web.Mvc.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17() +33
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +853420
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +265
   System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +837892
   System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +28
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +65
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +51
   System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult) +42
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +15
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +51
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
knocte
  • 16,941
  • 11
  • 79
  • 125

1 Answers1

5

So the problem you are experiencing is a know limitation of the dynamic keyword and explicit interface implementations. Unfortunately Map will have this problem too. If you really want to use a ViewBag like this, you could use an actual Dictionary<int,int>.

Ultimately, however you should play to F#'s strengths, which is static typing and low ceremony type creation. Create lightweight types in your F# code and use the @model keyword in your views.

Community
  • 1
  • 1
jbtule
  • 31,383
  • 12
  • 95
  • 128
  • why does ViewBag use a dynamic keyword, and where can I see an example of @model used with F#? – knocte Mar 24 '14 at 15:27
  • 2
    Because that's the point of a [ViewBag](http://stackoverflow.com/a/14985891/637783). In regards to `@model`, define a type or record, instantiate it, return it with `this.View(model) :> ActionResult` reference the type in your view with `@model Namespace.ModelType`, it's pretty straight forward, and not any different from C#. – jbtule Mar 24 '14 at 15:36
  • ok thanks! will try that this evening and upvote accordingly :) – knocte Mar 24 '14 at 15:46