asp.net-corequery-stringasp.net-core-viewcomponent

How to Redirect to a view from a viewcomponent while passing a value via URL?


I have a following method inside a viewcomponent

 public async Task<IViewComponentResult> InvokeAsync (ToolModel model)
        {
            if (!ModelState.IsValid)
            {
                return View();
            }

            //Code

            return await Task.FromResult((IViewComponentResult)View(FullPathsOfViews.FileDownload, fileName));
        }

There is an another view called Download and I want to redirect to this View after executed the above code, Also need to send the fileName via URL and catch it from the download controller.

Here is the download controller

[HttpPost]
[Route("download/{file}")]
public async Task<IActionResult> Download(string fileName)
{
    string fileName = HttpContext.Request.Query["download"].ToString();

    string wwwPath = string.Empty;
    string FilePath = string.Empty;

    wwwPath = this.env.WebRootPath;

    FilePath = string.Format("{0}\\file-convertions\\{1}", wwwPath, fileName);


    byte[] fileBytes = null;

    // Download Word file
    if (!string.IsNullOrEmpty(FilePath))
    {
        fileBytes = System.IO.File.ReadAllBytes(FilePath);

    }
    return File(fileBytes, "application/force-download", "ddd");
}

I want to URL be like

https://www.test.com/download/rt82x3267skykv34l8b3x4rnrrz1yz0g4cssd.pdf

How to achieve this? I am a beginner


Solution

  • Imagine there is a file upload button inside this view component. After file upload into a specific location I want to redirect to a page called Download and in there I need to find that file and download. I cannot find resources to redirect from viewcomponent to a view.

    Well, based on your comment and previous qustion it appeared that, you want to upload file using the viewcomponent and after uploading you want a download link back to the viewcomponent. If so you can achieve that using the same viewcomponent.

    What we will achieve:

    Let's assume, we have view component as following:

    enter image description here

    We want to upload a file and then want to show a download link back to the same view compoent as following:

    enter image description here

    How to achieve:

    All you need a model with download property name where we would be passing either downloaded file or full link (I would prefer file name to pass in download controller as a parameter). Finally, within the viewcomponent using anchor tag along with <a asp-action will can redirect to download page.

    Let's have a look in action how we can implement that;

    Model:

    public class UploadComponentModel
        {
            public IFormFile? MyUploadedFile { get; set; } = null;
            public string? FileExtntionName { get; set; } = string.Empty;
            public string? UploadedFileName { get; set; } = string.Empty;
            public string? FileExtentionMessage { get; set; } = string.Empty;
            public string? DownloadLink { get; set; } = string.Empty;
        }
    

    Note: For my demo I have used above property but IFormFile and DownloadLink are our main foucs. You can customize as per your need.

    View Component:

    @model DotNet6MVCWebApp.Models.UploadComponentModel
    <div class="col-sm-4">
        <div class="card" style="width: 18rem; margin-bottom:20px;box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
            <div class="card-body">
                <form asp-controller="FileUploadViewComponent" asp-action="Index" enctype="multipart/form-data">
                    <div class="card card-body">
                        <strong>Select PDF file to convert</strong> <div id="chooseFile"><input type="file" asp-for="MyUploadedFile" accept="image/*" /></div>
                        <br />
                    </div>
                    <br />
                    <input type="submit" value="Upload" class="btn btn-primary" />
                    <input asp-action="Clear" type="submit" value="Clear" class="btn btn-outline-primary" />
                    <br />
                    @{
                        if (Model.FileExtntionName == string.Empty || Model.UploadedFileName == string.Empty || Model.FileExtentionMessage == string.Empty)
                        {
    
                        }
                        else
                        {
                            <label asp-for="FileExtntionName" class="control-label">File Type: @Model.FileExtntionName</label>
                            <br />
                            <label asp-for="UploadedFileName" class="control-label">File Name: @Model.UploadedFileName</label>
                            <br />
                            <label asp-for="UploadedFileName" class="control-label" style="color:red">Note: @Model.FileExtentionMessage</label>
                            <a asp-action="DownloadFile" class="bi bi-download" asp-route-downloadlink="@Model.DownloadLink">Download File</a>
                        }
                    }
                </form>
            </div>
        </div>
    
    </div>
    

    Note: As you can see, I am using a conditional and at the beginning not showing any file info or download link, after executing upload action it will be rendered with our download link/fine name and other info we want. Point that, we are using asp action and passing controller parameter as asp-route-downloadlink="@Model.DownloadLink".

    Controller action when upload :

    public async Task<IActionResult> Index(UploadComponentModel FileName)
            {
    
                var uploadedFileDetails = new UploadComponentModel();
                if (FileName.MyUploadedFile == null)
                {
                    return View(uploadedFileDetails);
                }
                else
                {
                    string checkFileExtension = System.IO.Path.GetExtension(FileName.MyUploadedFile.FileName);
    
                    string[] expectedFile = { ".pdf", ".png", ".jpeg" };
    
                    if (expectedFile.Contains(checkFileExtension))
                    {
                        //Save file into directory
                        var path = Path.Combine(_environment.WebRootPath, "ViewComponentUpload", FileName.MyUploadedFile.FileName);
                        using (FileStream stream = new FileStream(path, FileMode.Create))
                        {
                            await FileName.MyUploadedFile.CopyToAsync(stream);
                            stream.Close();
                        }
    
                        uploadedFileDetails.FileExtentionMessage = "Right extension uploaded";
                        uploadedFileDetails.MyUploadedFile = FileName.MyUploadedFile;
                        uploadedFileDetails.FileExtntionName = checkFileExtension;
                        uploadedFileDetails.UploadedFileName = FileName.MyUploadedFile.FileName;
                        uploadedFileDetails.DownloadLink = FileName.MyUploadedFile.FileName;
                    }
                    else
                    {
                        uploadedFileDetails.MyUploadedFile = FileName.MyUploadedFile;
                        uploadedFileDetails.FileExtntionName = checkFileExtension;
                        uploadedFileDetails.UploadedFileName = FileName.MyUploadedFile.FileName;
                        uploadedFileDetails.FileExtentionMessage = "Invalid file type";
                        uploadedFileDetails.DownloadLink = "Sorry no download link available!";
                    }
                 
               
    
                   
                    return View(uploadedFileDetails);
                }
    

    Note: Here, I am uploading file in a wwwroot folder and I have that location which I can pass to the download controller action, it could full link or only file name. I prefer fine name because I can directly extract the file by file name from directory. I have following directory:

    enter image description here

    Download action within same controller:

    public async Task<IActionResult> DownloadFile(string downloadlink)
            {
                var path = Path.GetFullPath("./wwwroot/ViewComponentUpload/" + downloadlink);
                MemoryStream memory = new MemoryStream();
                using (FileStream stream = new FileStream(path, FileMode.Open))
                {
                    await stream.CopyToAsync(memory);
                }
                memory.Position = 0;
                return File(memory, "image/png", Path.GetFileName(path));
            }
    

    Output:

    enter image description here

    Note: Furthermore, you could explore few additional helpful resources here in official document.