(完结).NET Core第30天_Controller Action的各种不同回传

这里一样新增好一个专案
https://ithelp.ithome.com.tw/upload/images/20210930/20107452D2bZMGyYdi.png

https://ithelp.ithome.com.tw/upload/images/20210930/20107452FJB0jmeTYC.png

预设建立的专案可以看到每个action 回传型别都为一个IActionResult的interface,每一个回传型别都会去实作该介面,有泛型意味。

ContentResult

可以用於指定一班文字回传或者不同MIME型态的内文

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Net5AppDiffAction.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Net5AppDiffAction.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }


        public ContentResult GreetUser_GeneralStr()
        {
            return Content("Hello world from .net core mvc");
        }

        public ContentResult GreetUser_HTML()
        {
            return Content("<div><b>Hello world from .net core mvc</b></div>","text/html");
        }

        public ContentResult GreetUser_XML()
        {
            return Content("<div><b>Hello world from .net core mvc</b></div>", "text/xml");
        }

    }
}

效果

https://ithelp.ithome.com.tw/upload/images/20210930/20107452OvDEqzBc2r.png

最常用的

ViewResult
回传一个画面

public ViewResult TodoList()
{
    ViewBag.Message = "Todo List test";
    return View();
}

https://ithelp.ithome.com.tw/upload/images/20210930/20107452MvwOjyyomS.png

效果
https://ithelp.ithome.com.tw/upload/images/20210930/20107452SDqDUynBrl.png

RedirectResult

网页跳转
有分两种一般跳转(status code:302)
跟永久跳转(status code:301)

public RedirectResult GotoURL()
{
    return Redirect("http://www.google.com"); //HTTP status code : 302
}

public RedirectResult GotoURLPermanently()
{
    return RedirectPermanent("http://www.google.com"); //HTTP status code : 301
}

永久跳转(status code:301)
通常若是要转向到既有的档案或自己站内的页面
会建议用永久跳转,有助於SEO成效。
如果资源已被永久删除,将不再是先前的位置访问。大部分Browser
都会缓存此响应并自动执行重定向,而无需再次请求原始资源。

一般跳转(status code:302)

若想验证回传的status code可以下载Fiddler来自行测试
https://ithelp.ithome.com.tw/upload/images/20210930/20107452IP4b7GpgXk.png

当Press Enter後即可从左侧观察的到status code回传对应结果
https://ithelp.ithome.com.tw/upload/images/20210930/20107452e1Ugq1JNX2.png

https://ithelp.ithome.com.tw/upload/images/20210930/20107452roCnj2KzEX.png

RedirectToActionResult

跳转到指定的action可传相应的参数

public ViewResult TodoList(string Message = "Default Message for TodoList Test")
{
    ViewBag.Message = Message;
    return View();
}

public RedirectToActionResult GotoContactsAction()
{
    return RedirectToAction("TodoList", new { Message = "I am coming from a different action..." });
}

效果

https://ithelp.ithome.com.tw/upload/images/20210930/20107452KnnypWDttn.png

RedirectToRouteResult

藉由route的跳转

在startup.cs中做一些route的设置修改

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Net5AppDiffAction
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "TodoListRoute",
                    pattern: "GotoAbout",
                    defaults: new { controller = "Home", action = "TodoList" });


                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

这里在HomeController.cs新增的这个action就是去透过指定route来做相应跳转

public RedirectToRouteResult GotoAbout()
{
    return (RedirectToRoute("TodoListRoute"));
}

这里要注意各自对应参数要一致
https://ithelp.ithome.com.tw/upload/images/20210930/20107452KFDW8ClOLs.jpg

效果
https://ithelp.ithome.com.tw/upload/images/20210930/20107452Z3STeNs1Zf.png

FileResult

用於文档下载

public FileResult DownloadFile()
{
    return File("/css/site.css","text/plain","download_newsite.css");
}

public FileResult ShowLogo()
{
    return File("./Images/logo.png","images/png");
}

效果
https://ithelp.ithome.com.tw/upload/images/20210930/20107452xM29isoUt4.png

https://ithelp.ithome.com.tw/upload/images/20210930/20107452UcVZZTOMl5.png

FileContentResult

和FileResult不同点在於传入参数要是binary型态
且结果不会下载而是直接呈现在网页上

这里准备预设./wwwroot/css/site.css和./Data/Products.xml两种档案
https://ithelp.ithome.com.tw/upload/images/20210930/201074528eSL7QBRtW.png

测试的action

public FileContentResult DownloadContent_css()
{
    var testFile = System.IO.File.ReadAllBytes("./wwwroot/css/site.css");
    return new FileContentResult(testFile,"text/plain");
}

public FileContentResult DownloadContent_xml()
{
    var testFile = System.IO.File.ReadAllBytes("./Data/Products.xml");
    return new FileContentResult(testFile, "text/xml");
}

效果
https://ithelp.ithome.com.tw/upload/images/20210930/20107452otIXG7icDt.png

FileStreamResult

把文本内容透过stream形式写入来做档案下载

public FileStreamResult CreateFile()
{
    var stream = new System.IO.MemoryStream(System.Text.Encoding.ASCII.GetBytes("Hello FileStreamResult"));
    return new FileStreamResult(stream, new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("text/plain"))
    {
        FileDownloadName = "test.txt"
    };
}

效果
https://ithelp.ithome.com.tw/upload/images/20210930/20107452EehfNbLyww.png

VirtualFileResultPhysicalFileResult

虚拟档案路径(相对路径一定要存放wwwroot下的目录)

实际硬碟档案路径(要指定实际硬碟绝对路径)
这里我们注入IWebHostEnvironment 间接取得站台根目录

测试程序

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Net5AppDiffAction.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Net5AppDiffAction.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly IWebHostEnvironment _environment;

        public HomeController(ILogger<HomeController> logger, IWebHostEnvironment enviroment)
        {
            _logger = logger;
            _environment = enviroment;
        }

        public VirtualFileResult VirtualFileResultDemo()
        {
            return new VirtualFileResult("/css/site.css", "text/plain");
        }

        public PhysicalFileResult ShowProducts()
        {
            return new PhysicalFileResult(_environment.ContentRootPath + "/Data/Products.xml", "text/xml");
        }

        public PhysicalFileResult PhysicalFileResultDemo()
        {
            return new PhysicalFileResult(_environment.ContentRootPath + "/wwwroot/css/site.css", "text/plain");
        }
    }
}

效果
https://ithelp.ithome.com.tw/upload/images/20210930/20107452dW5GtpQ3uL.png

JsonResult

这里准备创建好一个 model class Products
https://ithelp.ithome.com.tw/upload/images/20210930/20107452fMizwnz97a.png

写回传Json result的 action

public JsonResult ShowNewProducts()
{
    Products prod = new Products() { ProductCode = 101, ProductName = "Printer", Cost = 1500 };
    return Json(prod);
}

藉由JsonResult序列化物件至JSON格式字串
https://ithelp.ithome.com.tw/upload/images/20210930/20107452UG6UkOpYXU.png
运行效果
https://ithelp.ithome.com.tw/upload/images/20210930/20107452UwyNdzBUOH.png

EmptyResult 和 NoContentResult

测试action

public EmptyResult EmptyResultDemo()
{
    return new EmptyResult();
}


public NoContentResult NoContentResultDemo()
{
    return NoContent();
}

各自差异在於
NoContentResult status code返回204
https://ithelp.ithome.com.tw/upload/images/20210930/20107452xldyvh8rX1.png
EmptyResult status code则是预设的200返回
https://ithelp.ithome.com.tw/upload/images/20210930/20107452gFNSYSuFdh.png

使用时机
当你不想有任何response显示在网页上的时候
而同时也不想throw 出error直接给client端的时候
就会看你是倾向告知user你查询结果为空(NoContentResult)
或者执行过程有错(EmptyResult)

若想验证回传的status code可以下载Fiddler来自行测试

本文同步发表至个人部落格(分两篇->因为铁人赛规划30天原先blog分两篇章)
.NET Core第31天_Controller Action的各种不同回传(ContentResult,ViewResult,RedirectResult,RedirectToActionResult,RedirectToRouteResult,FileResult)_part1
https://coolmandiary.blogspot.com/2021/08/net-core31controller.html

.NET Core第32天_Controller Action的各种不同回传(FileContentResult,FileStreamResult,VirtualFileResult,PhysicalFileResult,JsonResult,EmptyResult,NoContentResult)_part2
https://coolmandiary.blogspot.com/2021/09/net-core32controller.html

虽然没有成功连续不中断每天发文
但仍然期许之後下次比赛可以挑战成功
希望文章可以对於同样新手学习有帮助

Ref:
Response.Redirect() vs Response.RedirectPermanent()
https://stackoverflow.com/questions/16537955/response-redirect-vs-response-redirectpermanent

Redirect() vs RedirectPermanent() in ASP.NET MVC
https://stackoverflow.com/questions/17517318/redirect-vs-redirectpermanent-in-asp-net-mvc

RedirectPermanent
https://www.c-sharpcorner.com/forums/redirectpermanent

FileResult In ASP.NET Core MVC
https://www.c-sharpcorner.com/article/fileresult-in-asp-net-core-mvc2/

认识 ASP․NET Core 档案提供者与透过 Web API 下载实体档案
https://blog.miniasp.com/post/2019/12/08/Understanding-File-Providers-in-ASP-NET-Core-and-Download-Physical-File

File Providers in ASP.NET Core
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/file-providers?view=aspnetcore-3.1&WT.mc_id=DT-MVP-4015686

ASP.NET Core MVC returning file using FileResult
https://geeksarray.com/blog/aspnet-core-mvc-returning-file-using-fileresult


<<:  Day23-"其他排序方法"

>>:  Day15 开发套件 - 实作MethodChannel

Spring Framework X Kotlin Day 7 Docker & CI

GitHub Repo https://github.com/b2etw/Spring-Kotlin...

Day21-React 简易动画篇-下篇

这篇要继续介绍剩下的两个元件。 SwitchTransition 元件 主要是用来渲染两个状态间做切...

英雄列表范例:修改英雄

为了让使用者更直觉的修改,我希望能直接点英雄的名字就切换成可修改的输入元件,修改完後就直接存回後端。...

【Day 05】从零开始的 Line Chatbot-公开 APP 网址

昨天稍微简介了一下 ngrok 在做甚麽,今天我们要让我们的 Line Channel 公开,这个 ...

[30天 Vue学好学满 DAY30] 总结 & 完赛感言

最後一篇文,挤出了一些觉得在开发上容易踩的雷以及要注意的事情 要使用、渲染的变数除了传递进入元件的,...