Normally, lift will look for a "view" that satifying an HTTP request. A view is an XHTML page or segment of a page with special <lift:xxx> processing instructions in it (e.g., an instruction to embed a controller, an instruction to surround the XHTML with another template, etc.) However, in certain cases, for example, when you want to satisfy a Web Services (REST) request, you can use Scala's pattern matching to intercept a request and service it with a "short lived" controller (rather than lift's normal long-lived, Actor-based controllers.)

It's easy to "dispatch" incoming HTTP requests. In your "Boot" class create a `PartialFunction` that matches a pattern related to the incoming request and then create a short-lived controller to service the request.

    /**
      * A class that's instantiated early and run.  It allows the application
      * to modify lift's environment
      */
    class Boot {
      def boot {

        val dispatcher: PartialFunction[{RequestState, List[String],
          (String) => java.io.InputStream},
          (HttpServletRequest) => Option[Any]] = {
        case {r, "webservices" :: c :: Nil, _} => {
              (req: HttpServletRequest) => {
              val rc = new WebServices(r, req)
              val invoker = createInvoker(c, rc)
              invoker match {
                case None => None
                case Some(f) => f()
              }
              }
            }
        }
        Servlet.addBefore(dispatcher)
      }
    }

This code matches all the requests to "/webservices/????" and assigns the stuff in '????' to the variable `c`. Then the code attempts to find a public method with that name on the controller. If the method exists, it's invoked and lift processes the result.

You can see a couple of examples:
All Users in the database
Add a User to the database

      def add_user: XmlResponse = {
        var success = false
        for (val firstname <- params("firstname");
             val lastname <- params("lastname");
             val email <- params("email")) {
          val u = new User
          u.firstName := firstname
          u.lastName := lastname
          u.email := email
          params("textarea").map{v => u.textArea := v}
          params("password").map{v => u.password := v}
          success = u.save
        }

        XmlResponse(<add_user success={success.toString}/>)
      }

The controller simply validates that the required parameters exist (the `for` block.) If they do, they are assigned, the optional parameters are assigned, and the user is saved.