Actions must return a revel.Result, which handles the HTTP response generation and adheres to the simple interface:
revel.Controller provides a few methods to produce different results:
- `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 override
those defaults, simply set those properties on the response:
func (c App) Index() revel.Result {
c.Response.Status = http.StatusTeapot
c.Response.ContentType = "application/dishware"
return c.Render()
}
You can override the default status code by setting one yourself:
func (c *App) CreateEntity() revel.Result {
c.Response.Status = 201
return c.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:
func (c MyApp) Action() revel.Result {
myValue := calculateValue()
return c.Render(myValue)
}
and to use myValue
in their template. This is usually more convenient than
constructing an explicit map, since in many cases the data will need to be
handled as a local variable anyway.
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 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()
func (c App) File() revel.Result {
f, _ := os.Open("/path/to/attachment.pdf")
return c.RenderFile(f, revel.Inline)
}
func (c App) Filename() revel.Result {
return c.RenderFileName("/path/to/attachment.docx", revel.Attachment)
}
Controller.RenderJSON() / Controller.RenderXML()
The application may call RenderJSON, RenderJSONP or RenderXML and pass in any Go type, usually a struct. Revel will serialize it using json.Marshal or xml.Marshal.
If results.pretty=true
in conf/app.conf
then serialization will be done using
MarshalIndent
instead, to produce nicely indented output for human consumption.
// Simple example
type Stuff struct {
Foo string ` json:"foo" xml:"foo" `
Bar int ` json:"bar" xml:"bar" `
}
func (c MyController) MyWork() revel.Result {
data := make(map[string]interface{})
data["error"] = nil
stuff := Stuff{Foo: "xyz", Bar: 999}
data["stuff"] = stuff
return c.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:
return c.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:
import ("net/http")
type MyHtml string
func (r MyHtml) 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
:
func (c *MyApp) Hello() revel.Result {
return MyHtml("<html><body>Hello Result</body></html>")
}