控制器


ZKWeb使用了独自编写的控制器和模板系统,不依赖于Asp.Net Webform和Mvc。
ZKWeb提供了对Http的抽象封装,不依赖于Asp.Net和Asp.Net Core。
获取当前Http上下文应该使用HttpManager.CurrentContext

和Asp.Net Mvc控制器的区别

ZKWeb的控制器不拥有状态,不像Mvc的控制器会带当前Http上下文和路由信息。
ZKweb的控制器不决定路径,路径需要通过各个函数的Action属性指定,Action属性可以指定完整的Url。

控制器的示例

Action属性需要指定完整的Url,Url前如果没有"/"会自动补上。
[ExportMany]属性在IoC容器提到过,用于注册组件到全局的容器。

[ExportMany]
public class ExampleController : IController {
    [Action("example/plain_text")]
    public IActionResult PlainText() {
        // 返回文本
        return new PlainResult("some plain text");
    }

    [Action("example/plain_string")]
    public string PlainString() {
        // 返回文本,返回类型是string时会自动使用PlainResult包装
        return "some plain string";
    }

    [Action("example/json")]
    public object Json(string name, int age) {
        // 有参数时会自动获取传入参数
        // 返回json,返回类型不是IActionResult或string时会自动使用JsonResult包装
        return new { name, age };
    }

    [Action("example/template")]
    public IActionResult Template() {
        // 返回模板
        return new TemplateResult("zkweb.examples/hello.html", new { text = "World" });
    }

    [Action("example/file")]
    public IActionResult File() {
        // 返回文件
        return new FileResult("D:\\1.txt");
    }
}

控制器的示例

提供的返回类型

ZKWeb提供了以下的返回类型,
如果需要返回其他类型的结果,可以自己编写继承IActionResult的类。

  • 返回文件
    • FileEntryResult(IFileEntry fileEntry, DateTime? ifModifiedSince = null)
  • 返回图片
    • ImageResult(Image image, ImageFormat format = null)
  • 返回Json序列化的结果
    • JsonResult(object obj, Formatting formatting = Formatting.None)
  • 返回纯文本
    • PlainResult(object obj)
  • 重定向到指定地址
    • RedirectResult(string url, bool permanent = false)
  • 返回数据流
    • StreamResult(Stream stream, string contentType = null)
  • 返回模板
    • TemplateResult(string path, object argument = null)

获取传入参数

如果action函数带有参数,会自动按参数的名称进行获取。
需要手动获取时可以使用HttpManager.CurrentContext.Request.Get<T>
下面两种写法可以获取到一样的参数

[ExportMany]
public class PostExampleController : IController {
    [Action("example/post_a", HttpMethods.POST)]
    public IActionResult PostA(string paramInUrl, string paramInBody, string name, int age) {
        return new JsonResult(new { name, age });
    }

    [Action("example/post_b", HttpMethods.POST)]
    public IActionResult PostB() {
        var request = HttpManager.CurrentContext.Request;
        var paramInUrl = request.GetQueryValue("paramInUrl");
        var paramInBody = request.GetFormValue("paramInBody");
        var name = request.Get<string>("name");
        var age = request.Get<int>("age");
        return new JsonResult(new { name, age });
    }
}

获取传入参数的示例

全局处理传入参数

上面PostA函数中的nameage参数会自动从Http上下文获取,
需要定义不同的获取逻辑可以注册并替换IActionParameterProvider
ZKWeb MVVM Demo中使用这个接口实现了自动的参数验证,可以查看这里的源代码

重载Action

ZKWeb支持替换现有的Action,例如添加一个插件把原有的页面处理全部重写。
替换Action时需要指定Action属性的OverrideExists参数。
替换Action的插件加载顺序需要在原插件的后面(且不能是同一个插件)。

[Action("/", OverrideExists = true)]
public IActionResult CustomIndexPage() {
    return new PlainResult("hello overridden action");
}

Action过滤器

Action过滤器的接口的定义如下

public interface IActionFilter {
    Func<IActionResult> Filter(Func<IActionResult> action);
}

过滤器可以分为全局过滤器和属性过滤器,
全局过滤器对所有Action有效,
属性过滤器只对标记的Action有效。

添加全局过滤器可以继承IActionFilter并标记[ExportMany]注册到容器中。
添加属性过滤器可以继承ActionFilterAttribute并标记继承的属性到Action上。