Base solution for your next web application

Activities of "system15"

Ok I still can't download a file from the database but it never hits the controller any ideas where I'm going wrong?

This is the typescript function that gets called on click (I only included relevant code):

   import { Http, Response, Headers, RequestOptions } from '@angular/http';
   
   constructor(
        injector: Injector,
        private _fileUploadsServiceProxy: FileUploadsServiceProxy,
        private _notifyService: NotifyService,
        private _tokenAuth: TokenAuthServiceProxy,
        private _activatedRoute: ActivatedRoute,
        private _fileDownloadService: FileDownloadService,
        private _searchService: SearchService,
        private http: Http
    ) {
        super(injector);
    }
   
    downloadFile(id: string): any {
        var headers = new Headers();
        headers.append('Content-Type', 'application/octetstream');
        headers.append('Authorization', 'Bearer ' + abp.auth.getToken());
        return this.http.get(`${AppConsts.remoteServiceBaseUrl}/FileUploadComponents/DownloadFile?id= ${id}`); 
    }

This is the FileUploadComponentsController.cs

        [HttpGet]
        public async Task<ActionResult> GetDownloadFile(Guid id)
        {
            if (id == null)
            {
                throw new UserFriendlyException("File not found.");
            }
            var file = await _fileUploadRepository.FirstOrDefaultAsync(id);
            var filename = file.FileName.ToString();
            var fileBytes = file.Content;
            return File(fileBytes, file.ContentType,file.FileName);
        }

I'll add the method to the controller in Web.Core.

Following the example in DemoUiComponentsController.cs @ismcagdas is there an example of how to pass parameters to the controller method as the UploadFiles method is different.

Thanks @ryancyq I have added the WrapResult to the method and tested the method using swagger api and inserted a file id from the database but it still doesn't download the file:

`Here is the code:

    /// <summary>
    /// Download the file from the database by id.
    /// </summary>
    /// <param name="id">The identifier.</param>
    /// <returns>The file.</returns>
    [WrapResult(WrapOnSuccess = false, WrapOnError = false)]
    public async Task<HttpResponseMessage> GetDownloadFile(Guid id)
    {
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        var file = await _fileUploadRepository.FirstOrDefaultAsync(id);
        var filename = file.FileName.ToString();
        var ms = new MemoryStream(file.Content);
        ms.Position = 0;
        result.Content = new StreamContent(ms);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = Uri.EscapeDataString(file.FileName)
        };

        return result;
    }

`

I am trying to download the file by id using this method but all it is doing is returning the HttpResponse in json format in swagger but what I'm trying to achieve is the file being download in the browser. Does anyone know what is needed to be done to get the correct outcome?

I have a FileUpload table that has the following columns (related to the file): Id = uniqueidentifier, Content = varbinary, ContentType = nvarchar, e.g. application/pdf FileName = nvarchar, e.g. filename.pdf FileType = tinyint e.g.

`Here is the method in the Project.Application

    /// <summary>
    /// Download the file from the database by id.
    /// </summary>
    /// <param name="id">The identifier.</param>
    /// <returns>The file.</returns>
    public async Task<HttpResponseMessage> GetDownloadFile(Guid id)
    {
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        var file = await _fileUploadRepository.FirstOrDefaultAsync(id);
        var filename = file.FileName.ToString();
        var ms = new MemoryStream(file.Content);
        ms.Position = 0;
        result.Content = new StreamContent(ms);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = Uri.EscapeDataString(file.FileName)
        };

        return result;
    }

`

`Here is the typescript in Web.Host

/// <summary> 
/// Download the file from the database by id.
/// </summary>
///<param name="id">The identifier.</param>
downloadFile(id: string, event) {
    if (id) {
        debugger;//Todo: remove.

        this._fileUploadsServiceProxy.downloadFile(id)
            .subscribe(result => {
                this.notify.success(`Downloaded successfully.`);
            });
    }
}

`

Thanks @ismcagdas the email template works!

No i haven't. I'll give that a try.

I have created a new html email template and I've put it in the same directory as the default.html file (Directory: myProject\src\myProject.Core\Emailing\EmailTemplates) with the ideas to be able to use a second template.

I have copied the following method and renamed it:
public string GetDefaultTemplate(int? tenantId) { using (var stream = typeof(EmailTemplateProvider).GetAssembly().GetManifestResourceStream("HomeDelivery.Emailing.EmailTemplates.default.html")) { var bytes = stream.GetAllBytes(); var template = Encoding.UTF8.GetString(bytes, 3, bytes.Length - 3); template = template.Replace("{THIS_YEAR}",DateTime.Now.Year.ToString()); return template.Replace("{EMAIL_LOGO_URL}", GetTenantLogoUrl(tenantId)); } }

New method that doesn't work when called: public string GetBasicTemplate(int? tenantId) { using (var stream = typeof(EmailTemplateProvider).GetAssembly().GetManifestResourceStream("HomeDelivery.Emailing.EmailTemplates.newTemplate.html")) { var bytes = stream.GetAllBytes(); var template = Encoding.UTF8.GetString(bytes, 3, bytes.Length - 3); return template.Replace("{THIS_YEAR}", DateTime.Now.Year.ToString()); //return template.Replace("{EMAIL_LOGO_URL}", GetTenantLogoUrl(tenantId)); } }

When debugging and the line gets to the var bytes part I get an exception object reference not set to an instance of an object.

Any ideas how to resolve this so that I can alternate between templates without issues.

Ok thanks

I already have that reference included in the project directory using webpack file "MyProject.Host\src\assets\metronic\src\js\framework\components\general" I had to add [(ngModel)]="searchFilterText" to the element that I wanted it to work on because the quicksearch.js javascript is trying to make an ajax call to the endpoint and because the bearer token is not provided I get a 401 unauthorized.

Summary of what I've done for clarity so far:

  1. Added [(ngModel)]="searchFilterText" to the search input field.
  2. In the type script file for that html template e.g. header component.html, header.component.ts handle the search term value for processing using keyup.enter on the search element.
  3. Here is the search element below:

<input autofocus #search (keyup.enter)="onEnter(search.value)" [(ngModel)]="searchFilterText" id="m_quicksearch_input" autocomplete="off" type="text" name="searchFilterText" class="m-list-search__form-input" value="" placeholder="Search...">

So I can talk to the endpoint using step 3 above.

    /// <summary>
    /// Process the search term provided when the enter key is pressed on the input field.
    /// </summary>
    /// <param name="searchTerm">The search term.</param>
    onEnter(searchTerm: string) {
        if (searchTerm != null || searchTerm != undefined) {
            //Get client info.
            this.getData(searchTerm.trim());
        }
    }

What is your thoughts on using this solution?

Hi there the angular project and version is: ASP.NET CORE & Angular (single solution) .NET Framework 4.6.1 v5.3.0

Showing 1 to 10 of 49 entries