7

I have this action method in C#:

  public ActionResult Index() {
      ViewBag.Message = "Hello";
      return View();
  }

And this view (Index.cshtml):

  <h2>@ViewBag.Message</h2>

And this produces the expected "Hello" on the page.

I want to do the controller in F#. I've tried

type MainController() =
  inherit Controller()
  member x.Index() =
    x.ViewBag?Message <- "Hello"
    x.View()

And this produces the error message "Method or object constructor 'op_DynamicAssignment' not found".

I've looked at some of the F# code samples for the dynamic operator, and I can't see anything that's shorter than several pages of description and many lines of code. They seem to be too general for just this property "setter".

Stephen Hosking
  • 1,405
  • 16
  • 34

3 Answers3

12

The ViewBag property is just a wrapper that exposes the ViewData collection as a property of type dynamic, so that it can be accessed dynamically from C# (using property set syntax). You could use implementation of ? based on DLR to do that (see this discussion at SO), but it is easier to define ? operator that adds data directly to ViewDataDictionary (which is exposed by the ViewData property):

let (?<-) (viewData:ViewDataDictionary) (name:string) (value:'T) =
  viewData.Add(name, box value)

Then you should be able to write

x.ViewData?Message <- "Hello"
Community
  • 1
  • 1
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • #Tomas Giving credit where it's due, I used your F# Empty Web Template, described in http://msdn.microsoft.com/en-us/library/hh304375.aspx, to generate this code in just a minute (but the problem did arise in a real project). – Stephen Hosking Nov 16 '11 at 23:12
  • I needed to provide it for TempData as well, so changed the first paramater to `(dictionary:IDictionary)` – Stephen Hosking Mar 19 '12 at 01:17
  • Could you elaborate on how F# knows where to split the operator? It seems weird to have `(?<-)`, and using it as `x.y?z <- q` – Anemoia Apr 26 '16 at 10:03
  • It is not a general features - the F# compiler treats `?<-` in a special way - and there is no way for defining similar operators on your own. – Tomas Petricek Apr 26 '16 at 12:09
1

Instead of

x?ViewBag <- "Hello"

Try:

x.ViewBag?Message  <- "Hello"
Ankur
  • 33,367
  • 2
  • 46
  • 72
  • Thankyou. I've done that but it still produces "Method or object constructor 'op_DynamicAssignment' not found". I've edited that question to include this suggestion. – Stephen Hosking Nov 17 '11 at 01:39
0

Just to provide a similar example, the MvcMovie example in the ASP.NET Core docs uses the following controller method:

public IActionResult Welcome(string name, int numTimes = 1)
{
    ViewData["Message"] = "Hello " + name;
    ViewData["NumTimes"] = numTimes;

    return View();
}

converted to F#:

member this.Welcome (name : string, num_times : int) =
    this.ViewData.Add("Message", box ("Hello " + name))
    this.ViewData.Add("NumTimes", box num_times)

    this.View()    
dharmatech
  • 8,979
  • 8
  • 42
  • 88