Custom ActionResult in ASP.NET Core and MVC 6

 

        Introduction:

 

                 ActionResult in ASP.NET Core has been improved because it can be now asynchronous. Means action result now have ActionResult.ExecuteResultAsync in addition to ActionResult.ExecuteResult. Infect IActionResult only have ExecuteResultAsync. So, we have now option to create custom action result with async support. In this article, I will show how to create a custom ActionResult with async support in ASP.NET Core.

 

        Description:

 

                    Currently, ASP.NET Core is missing file action result(it will be there for sure, AFAIK). Here is, how we can create a simple custom async action result,

 

    public class FileResult : ActionResult
    {
        public FileResult(string fileDownloadName, string filePath, string contentType)
        {            
            FileDownloadName = fileDownloadName;
            FilePath = filePath;
            ContentType = contentType;
        }

        public string ContentType { get; private set; }
        public string FileDownloadName { get; private set; }
        public string FilePath { get; private set; }

        public async override Task ExecuteResultAsync(ActionContext context)
        {
            var response = context.HttpContext.Response;
            response.ContentType = ContentType;
            context.HttpContext.Response.Headers.Add("Content-Disposition", new[] { "attachment; filename=" + FileDownloadName });
            using (var fileStream = new FileStream(FilePath, FileMode.Open))
            {
                await fileStream.CopyToAsync(context.HttpContext.Response.Body);
            }
        }
    }

 

                    Here I am overriding ExecuteResultAsync and using famous CopyToAsync method to copy the file contents to response body. Here is how we can use this custom action result in our controller,

 

    public class HomeController : Controller
    {
        private readonly IApplicationEnvironment _appEnvironment;

        public HomeController(IApplicationEnvironment appEnvironment)
        {
            _appEnvironment = appEnvironment;
        }

        public virtual FileResult File(string fileDownloadName, string filePath, string contentType = "application/octet-stream")
        {
            return new FileResult(fileDownloadName, filePath, contentType);
        }

        public ActionResult ReadMe()
        {
            return File("readme.txt", _appEnvironment.ApplicationBasePath + "\\a.txt");
        }

        public IActionResult About()
        {
            return File("about.xml", _appEnvironment.ApplicationBasePath + "\\a.xml", "application/xml");
        }       
    }

 

                    Note that I am using IApplicationEnvironment to get the application base path because there is no Server.MapPath method in Core.

                    Update: File action result is now available with this commit.  

 

                   

        Summary:

                    We have now async action result support in ASP.NET Core. In this article, I showed you how to create a custom async result in ASP.NET Core.

2 Comments

  • Sorry for posting this here as the comments to the original post are disabled, but it is about one of your contributions in GitHup

    I have commented on the code you provided about (Onion Arch with Identity).
    https://github.com/imranbaloch/ASPNETIdentityWithOnion/commit/eb7c0bee85474a1413cc1459616da8b3f99be236#commitcomment-8308385

    this is the comment in the EFConfig File..
    __________

    Hello, Thanks for sharing this, I am using this methodology, but here I can't seem to link the Domain Models with the identity tables:
    for example: AppUser, ApplicationRole, ApplicationUserRole, etc..
    with : ApplicationIdentityUser, ApplicationIdentityRole, ApplicationIdentityUserRole, et...

    these classes don't share the default tables from the IdentityDbContext like (AspNetUsers, AspNetRoles, AspNetUserRoles, etc ...)

    can you provide a way to link the above ? because in your example there is no link between users and products or images, these are completly to different domains.

    if for example you can put a navigation property in the "Product" class to the "AppUser", so that we can know which use added this product,
    if you do so, 3 new tables(ApplicationRoles, ApplicationUserRoles, ApplicationUserClaims), will appear along with the 5 types already provided by the IdentityDbContext,
    so who would I merge the tables ?

  • @Zaid I am too busy these days, I will check when I get some time. Sorry about this

Comments have been disabled for this content.