iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
自我挑戰組

.NET Core MVC網頁應用開發系列 第 30

(完結).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


上一篇
.NET Core第29天_Model驗證配置準備流程_各種驗證資料註解使用方式
系列文
.NET Core MVC網頁應用開發30

尚未有邦友留言

立即登入留言