Actions must return a revel.Result, whichhandles the HTTP response generation and adheres to the simple interface:

  1. typeResultinterface{Apply(req*Request,resp*Response)}

revel.Controller provides a fewmethods to produce different results:

NOTE: From v0.14, the following changes:

  • RenderJson is now RenderJSON
  • RenderJsonP is now RenderJSONP
  • RenderXml is now RenderXML

  • Render(), RenderTemplate()

    • render a template, passing arguments.
  • RenderJSON(), RenderXML()
    • serialize a structure to json or xml.
  • RenderText()
    • return a plaintext response.
  • Redirect()
    • redirect to another action or URL
  • RenderFile(), RenderFileName()
    • return a file inline or to be downloaded as an attachment.
  • RenderError()
    • return a 500 response that renders the errors/500.html template.
  • NotFound()
    • return a 404 response that renders the errors/404.html template.
  • Todo()
    • return a stub response (500)
      Additionally, the developer may define a result with CustomResult and return that.

Setting the Status Code / Content Type

Each built-in Result has a default HTTP Status Code and Content Type. To overridethose defaults, simply set those properties on the response:

  1. func(cApp)Index()revel.Result{c.Response.Status=http.StatusTeapotc.Response.ContentType="application/dishware"returnc.Render()}

You can override the default status code by setting one yourself:

  1. func(c*App)CreateEntity()revel.Result{c.Response.Status=201returnc.Render()}

Controller.Render()

Called within an action (e.g. “Controller.Action”),Controller.Render() does two things:

  • Adds all arguments to the controller’s ViewArgs, using their local identifier as the key.
  • Executes the template “views/Controller/Action.html”, passing in the controller’s ViewArgs as the data map.
    If unsuccessful (e.g. it could not find the template), an ErrorResult is returned instead.

This allows the developer to write:

  1. func(cMyApp)Action()revel.Result{myValue:=calculateValue()returnc.Render(myValue)}

and to use myValue in their template. This is usually more convenient thanconstructing an explicit map, since in many cases the data will need to behandled as a local variable anyway.

Note: Revel looks at the calling method name to determine the Templatepath and to look up the argument names. Therefore, c.Render() may only be called from Actions.

  1. // Example using mix of render args and variables// This renders the `views/MyController/showSutuff.html` template as// eg <pre>foo={{.foo}} bar={{.bar}} abc={{.abc}} xyz={{.xyz}}</pre>func(cMyController)ShowStuff()revel.Result{c.ViewArgs["foo"]="bar"c.ViewArgs["bar"]=1abc:="abc"xyz:="xyz"returnc.Render(xyz,abc)}// Example renders the `views/Foo/boo.xhtml` tempatefunc(cMyController)XTemp()revel.Result{c.ViewArgs["foo"]="bar"c.ViewArgs["bar"]=1returnc.RenderTemplate("Foo/boo.xhtml")}

Controller.RenderFile() / Controller.RenderFileName()

Within an action it is sometimes necessary to serve a file (e.g. an attachment).For this case the functions Controller.RenderFile() and For this case the functions Controller.RenderFileName() are there.

The main difference is that Controller.RenderFile() needs an *os.File and Controller.RenderFileName() takes a file path as a string. Both require a Content-Disposition option which can be revel.Attachment or revel.Inline.

  • revel.Attachment forces the browser to download the file. The filename and size are derived from the passed *os.File or file path.
  • revel.Inline indicates the browser that it may render the file inline. Note that when browsers can’t display the file a download is still performed.
  • revel.NoDisposition omits the content disposition header and let the browser figure out what to do, also omits the file name from the header.
    Controller.RenderFileName() can also return an error in case the file is not found. See Controller.RenderError()
  1. func(cApp)File()revel.Result{f,_:=os.Open("/path/to/attachment.pdf")returnc.RenderFile(f,revel.Inline)}func(cApp)Filename()revel.Result{returnc.RenderFileName("/path/to/attachment.docx",revel.Attachment)}

Controller.RenderJSON() / Controller.RenderXML()

The application may callRenderJSON, RenderJSONP orRenderXML and pass in any Gotype, usually a struct. Revel will serialize it usingjson.Marshal orxml.Marshal.

If results.pretty=true in conf/app.conf then serialization will be done usingMarshalIndent instead, to produce nicely indented output for human consumption.

  1. // Simple exampletypeStuffstruct{Foostring` json:"foo" xml:"foo" `Barint` json:"bar" xml:"bar" `}func(cMyController)MyWork()revel.Result{data:=make(map[string]interface{})data["error"]=nilstuff:=Stuff{Foo:"xyz",Bar:999}data["stuff"]=stuffreturnc.RenderJSON(data)// or alternately // return c.RenderXML(data)}

Redirect()

  • A helper function for generating HTTP redirects.
  • It may be used in two ways and both return a 302 Temporary Redirect HTTP status code.

    Redirect to an action with no arguments:

  1. returnc.Redirect(Hotels.Settings)
  • This form is useful as it provides a degree of type safety and independence from the routing and generates the URL automatically.

    Redirect to a formatted string:

return c.Redirect("/hotels/%d/settings", hotelId)

  • This form is necessary to pass arguments.
  • It returns a 302 Temporary Redirect status code.

Custom Result

Below is a simple example of creating a custom revel.Result.

Create this type:

  1. import("net/http")typeMyHtmlstringfunc(rMyHtml)Apply(req*revel.Request,resp*revel.Response){resp.WriteHeader(http.StatusOK,"text/html")resp.GetWriter().Write([]byte(r))}

Then use it in the action MyApp.Hello:

  1. func(c*MyApp)Hello()revel.Result{returnMyHtml("<html><body>Hello Result</body></html>")}
GoDoc Reference
GitHub Labels

原文: https://revel.github.io/manual/results.html