c# – Asp.Net overall design pattern integrating REST, dependency injection, and Hosted Services (See full project at Github)

I’m new to C#, and want to conform as much as possible to good design patterns. This code is the beginning of a Microservice, running as Asp.Net. It is based on a Microsoft tutorial doing similar work.

It has three functional components currently:

  1. Converts a CSV file to JSON, for return via REST
  2. A REST controller to test the conversion of the CSV to JSON return
  3. A background service which monitors a directory looking for changed files. The file attributes (Path, Date, Checksum) are stored in a MongoDB database via a Repository.

Opinions/Recommendations regarding the design patterns welcomed.

The full code can be found at: https://github.com/BioComSoftware/unite-radimaging-source-n2m2.git

BONUS: Notice in FileSearchHostedService.cs, I instantiate the Repository objects explicitly. I think it would be more appropriate to have them as Dependency Injection – but I couldn’t get it to work. Notice the commented-out lines that would have done this. My understanding is; I would need to do this with IScopedProcessingService – but I have no idea how to do this with this specific code.

Structure

(Startup.cs)

using unite.radimaging.source.n2m2.Data;
using unite.radimaging.source.n2m2.Repositories;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
//using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace unite.radimaging.source.n2m2 {
    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.AddControllers();

            services.AddScoped<IFoundFileContext, FoundFileContext>();
            services.AddScoped<IFoundFileRepository, FoundFileRepository>();
        }

        // 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();
            }
            app.UseExceptionHandler("/error");
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints => { 
                endpoints.MapControllers(); 
            });
        }
    }
}

(FoundFileRepository.cs)

using unite.radimaging.source.n2m2.Data;
using unite.radimaging.source.n2m2.Entities;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace unite.radimaging.source.n2m2.Repositories {
   public class FoundFileRepository : IFoundFileRepository {
       private readonly IFoundFileContext _context;
       public FoundFileRepository(IFoundFileContext context) {
           _context = context ?? throw new ArgumentNullException(nameof(context));
       }

       public async Task<IEnumerable<FoundFile>> GetFiles() {
       return await _context
           .FoundFiles
           .Find(p => true)
           .ToListAsync();
       }

       public async Task<FoundFile> GetFile(string id) {
           return await _context
                          .FoundFiles
                          .Find(p => p.Id == id)
                          .FirstOrDefaultAsync();
       }

       public async Task<FoundFile> GetFileByPath(string path) {
           return await _context
                          .FoundFiles
                          .Find(p => p.Path == path)
                          .FirstOrDefaultAsync();
       }

       public async Task<FoundFile> GetFileByChecksum(string checksum) {
           return await _context
                          .FoundFiles
                          .Find(p => p.Checksum == checksum)
                          .FirstOrDefaultAsync();
       }

       //public async Task<IEnumerable<FoundFile>> GetFileByMtime(string mtime) {
       //    FilterDefinition<FoundFile> filter = Builders<FoundFile>.Filter.ElemMatch<DateTime>(p => p.Mtime, mtime);

       //    return await _context
       //                    .FoundFiles
       //                    .Find(filter)
       //                    .ToListAsync();
       //}

       //public async Task<IEnumerable<FoundFile>> GetFileBySize(long size) {
       //    FilterDefinition<FoundFile> filter = Builders<FoundFile>.Filter.ElemMatch<long>(p => p.Size, size);

       //    return await _context
       //                    .FoundFiles
       //                    .Find(filter)
       //                    .ToListAsync();
       //}

       public async Task CreateFile(FoundFile foundFile) {
           await _context.FoundFiles.InsertOneAsync(foundFile);
       }

       public async Task<bool> UpdateFile(FoundFile foundFile) {
           var updateResult = await _context.FoundFiles.ReplaceOneAsync(
               filter: g => g.Path == foundFile.Path, replacement: foundFile);
           return updateResult.IsAcknowledged && updateResult.ModifiedCount > 0;
       }

       public async Task<bool> DeleteFile(string path) {
           FilterDefinition<FoundFile> filter = Builders<FoundFile>.Filter.Eq(p => p.Path, path);

           DeleteResult deleteResult = await _context
                                               .FoundFiles
                                               .DeleteOneAsync(filter);

           return deleteResult.IsAcknowledged
               && deleteResult.DeletedCount > 0;
       }
   }
}

(FileSearchHostedService.cs)

using unite.radimaging.source.n2m2.Repositories;
using unite.radimaging.source.n2m2.Entities;
using unite.radimaging.source.n2m2.Data;
using Serilog;
using Microsoft.Extensions.Configuration;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace unite.radimaging.source.n2m2.HostedServices {
    public class FileSearchHostedService : BackgroundService {
        private readonly IConfiguration _configuration;
        //private IFoundFileRepository _repository;

        public FileSearchHostedService(
            //IFoundFileRepository repository,
            IConfiguration configuration
            ) {
            //_repository = repository ?? throw new ArgumentNullException(nameof(repository));
            _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
        }

        protected override async Task ExecuteAsync(CancellationToken cancellationToken) {
            Log.Information("FileSearchHostedService: File searching started.");

            cancellationToken.Register(() => Log.Information("Processing service stopped"));

            //string checksum;
            string _current_path;
            FileInfo _current_file;
            FoundFile _foundFile;
            FoundFile _existingFile;
            FoundFile _addFoundFile;
            FoundFileContext FoundfileContext = new FoundFileContext(_configuration); // Normal instantiation, in leiu of injection
            FoundFileRepository _repository = new FoundFileRepository(FoundfileContext);  // Normal instantiation, in leiu of injection

            while (!cancellationToken.IsCancellationRequested) {
                Log.Information("Searching files...");
                string dir = _configuration.GetValue<string>("FileSearchSettings:SearchDir");
                string() files = Directory.GetFiles(dir);
                foreach (string filename in files) {
                    Log.Debug($"Parsing '{filename}'");

                    _current_file     = new FileInfo(filename);
                    _current_path = Path.GetFullPath(Path.Combine(_current_file.Directory.ToString(), _current_file.Name));

                    _foundFile = new FoundFile() {
                        Path = _current_path,
                        Size = _current_file.Length,
                        Mtime = _current_file.LastWriteTime,
                        Checksum = FileChecksum.getChecksum(filename)
                    };
                    Console.WriteLine("==========================");
                    _existingFile = await _repository.GetFileByPath (_current_path);
                    Console.WriteLine("past _repository.GetFileByPath");

                    try {
                        Console.WriteLine($"{_existingFile.Path} exists!!!");
                        Console.WriteLine($"     _existingFile.Checksum: {_existingFile.Checksum}");
                        Console.WriteLine($"     _existingFile.Length = {_existingFile.Size}");
                        Console.WriteLine($"     _existingFile.LastWriteTime = ({_existingFile.Mtime}");
                    }
                    catch {
                        Console.WriteLine($"Creating MongoDB for file {_foundFile.Path} ");
                        _addFoundFile = new FoundFile() {
                            Path = _foundFile.Path,
                            Size = _foundFile.Size,
                            Mtime = _foundFile.Mtime,
                            Checksum = _foundFile.Checksum
                        };
                        await _repository.CreateFile(_addFoundFile);
                    }
                }

                await Task.Delay(
                    _configuration.GetValue<int>("FileSearchSettings:Delay"),
                    cancellationToken
                    );
            }
        }
    }
}

applications – Running services in developer options is missing

I want to check the apps that are running in the background to stop them.
Android 10
MIUI 12
redmi note 7s (NOT ROOTED)

i tried a lot of apps from playstore they doesn’t seem to work properly (Doesn’t show the amount of ram used and not able to force close or end the background apps).

I also tried the developer options but there was NO option for “running services” in the developer options, is there a way to enable this in developer options.

iphone – What is “Safari services” listed in iOS cellular data usage?

When determining what’s eating up my cellular data I look at data usage in the settings app. There the biggest consumer by far is “system services” and inside that item “safari services” is responsible for 95% of all usage.

This doesn’t really tell me anything useful. What is Safari services? Who is it providing services for? Safari? 3rd party apps? Me? I assume it’s not to me or Safari since then I don’t see why the data isn’t just listed under the Safari app directly, and the same thing if it’s to 3rd party apps. If neither then I don’t see why it’s such a big consumer of data to begin with.

How do I cut down on its data consumption?

iOS 14.4 on iPhone 8

amazon web services – How do I download files restored from glacer?

I’ve got an s3 folder with a bunch of files stored on glacier. I’ve already restored them with s3 browser, and they can be downloaded to my pc using s3 browser. However, when I write

aws s3 sync s3://myfolder .

on the server, for which the files are intended, I get a bunch of skips with message

warning: Skipping file s3://myfolder/myfile. Object is of storage class GLACIER. Unable to perform download operations on GLACIER objects. You must restore the object to be able to perform the operation. See aws s3 download help for additional parameter options to ignore or force these transfers.

How do I properly sync this folder?

Rinulikes.com -seo Services + Facebook Youtube Instagram Twitter

Please read all carefully!

– Website: https://rinulikes.com/

-Youtube
Subscribers: 100 – 3$
Likes: 100-2$
Dislikes: 50 – 2$
Random/custom comments: 10 – 2$
Comments likes/dislikes: 100 – 2$
Shares(fb/tw/pt/g+/etc.): 100 – 1$
Views: 1000 – 3$

-Facebook
Page Likes: 100 – 2$
Photo/Post Likes: 100 – 2$
Photo/Post Reaction(Love/Funny/Wow/Sad/Angry): 100 – 1$
Video views: 1000 – 1$
Custom comments: 5 – 1$
Event interested/going: 100 – 2$
Profile followers: 100 – 2$

-Twitter
Followers: 100 – 2$
Retweets: 100 – 2$
Likes: 100 – 2$

-Instagram
Followers: 1000 – 8$
Likes/Autolikes: 1000 – 3$
Comments custom/random/emoji: 10 – 1$
Video views: 1000 – 1$

-Soundcloud
Plays: 1000 – 1$
Followers: 100 – 1$
Likes: 100 – 1$
Reposts: 100 – 1$
Comments: 10 – 1$

-Twitch
Followers: 1000 – 3$
Views: 1000 – 3$

-Spotify
Followers: 1000 – 5$
Plays: 1000 – 3$

-Tiktok
Followers: 100 – 2$
Likes: 100 – 2$

-Telegram
Members: 1000 – 5$

-Website Traffic
Website traffic: 1000 – 1$

Discount for higher amount on website.
For other services/social sites (pinterest, tiktok, linkedin, etc.) contact me.
Payment – Paypal, BTC/ETH/LTC, Perfect Money, Credit/Debit Card, Paysafecard, Skrill.
Refund/refill available! 30 days warranty on all services!
Start time will vary from a few hours and in rare cases up to 48-72 hours. Delivery can take from a few hours up to several days depending on service or quantity.
Worldwide services, speed varies and increases based on quantity.
All services are 100% safe and best quality on the market.
*Services/prices may change anytime so make sure to check the site for latest rates.
For a faster transaction, order via website or contact me via pm with your url + amount wanted.

SEO Packages:

Starter 15$ -50 Backlinks
Advanced 25$ -100 Backlinks
Ultimate 30$ -100 Backlinks + 100 Tier2 + 1000 Social signals

Web 2.0 Properties
Press Release Distribution
Article Submission
Social Bookmarking & Sharing
Classifieds Ads Posting
Directory Submissions
PDF Sharing
Video Creation & Sharing
Image Submission & Sharing
Social Media Sharing

High DA/PA
Mix dofollow/nofollow
Manual Tier1
Premium Indexing
Excel report

Required 1 URL and 1 up to 3 max keywords.
Non English sites are accepted however the content will be in English. Safe for new sites.
Report will be delivered to the provided email within 7-10 days depending on the workload.
Each keyword should contain at least 2 or 3 words or more for best results, long tail keywords recommended, it is also highly recommended to use kwfinder.com or spyfu.com/keyword/overview or similar sites for proper keyword research. Best results for low/medium competition keywords.
There is no guarantee that the website will go from page X to page Y, however there will be a boost in ranking, these services require time also (weeks/months) to see the improvements and it depends also on the niche, keyword difficulty, competition, on page SEO and other factors.
For better results, packages can be purchased on monthly subscription.
Adult/Pharma/Gambling and illegal websites/content are not accepted.

Social Signals:

1000+ Social Signals-6$
Required 1 url
Facebook Signals
Pinterest Signals
Twitter Signals

2000+ Social Signals-10$
Required 1 url
Facebook Signals
Pinterest Signals
Twitter Signals

Report will be delivered to the provided email within 5-10 days depending on the workload. Report will be presented as a screenshot/link from social signal checker website signalcount.com to protect the privacy of our network.
There is no guarantee that the website will go from page X to page Y, however there will be a boost in ranking, these services require time also (weeks/months) to see the improvements and it depends also on the niche, competition, website age, on page SEO and other factors.
For better results, packages can be purchased on monthly subscription.
Adult/Pharma/Gambling and illegal websites/content are not accepted.

SEO Services, Newbie Friendly! No EXP!

Make passive income by selling seo services, easy to run, newbie friendly, no experience needed

seohawk.xyz is perfect for beginners, newbies or anyone who want to own their own profitable, automated online business. This is a real fully functional business with a proven business model that will allow you to be in business from day one. You only need to generate targeted traffic to it. It’s a great opportunity for those who are just starting out online.

The suppliers for these services are top notch suppliers. You can rest easy that they will perform a great job fulfilling your customers’ orders while still offer incredible low rates for theirs services so that you can put a nice markup on their services.

How The Business Work?

You will be notified of a new order straight to your designated email inbox.
Instant payment will be sent to your Paypal account.
You forward that order to the suppliers that I supply you with along with their small fee.
Your supplier emails you once the order has been completed.
You email the customer to inform that that their order has been completed.

SEO SERVICE PACKAGE

1.RANK HERO

  • Silver Package: Sale Price $90 >> Supplier Charge $69 >> Profit : $21
  • Gold Package: Sale Price $142 >> Supplier Charge $109 >> Profit : $33

2.RANK AUTHORITY

  • Silver Package: Sale Price $90 >> Supplier Charge $69 >> Profit : $21
  • Gold Package: Sale Price $142 >> Supplier Charge $109 >> Profit : $33
  • Plarinum Package: Sale Price $265 >> Supplier Charge $204 >> Profit : $61

3.RANK BASE

  • Silver Package: Sale Price $55 >> Supplier Charge $25 >> Profit : $30
  • Gold Package: Sale Price $70 >> Supplier Charge $40 >> Profit : $30

4.RANK BUDDY

  • Bronze Package: Sale Price $129 >> Supplier Charge $99 >> Profit : $30
  • Silver Package: Sale Price $259 >> Supplier Charge $199 >> Profit : $60
  • Platinum Package: Sale Price $454 >> Supplier Charge $349 >> Profit : $105

5.SITE BOLT

  • Silver Package: Sale Price $85 >> Supplier Charge $55 >> Profit : $30
  • Gold Package: Sale Price $195 >> Supplier Charge $150 >> Profit : $45
  • Plarinum Package: Sale Price $390 >> Supplier Charge $300 >> Profit : $90

Features of the Business and the Website:
Fully Loaded easy to manage website
Integrated Back-End Support/Order Tracking System!
INTEGRATED Live Chat Support!
Professionally Created and designed website that your customers will trust.
LIST of RELIABLE Supplier.

What You Will Get:
Brandable Domain and easy to remember
COMPLETELY designed and functional website
All Files, Graphics, and Content on the site
WordPress Based Backend for easy site changes
Business with HUGE Potential
Reliable Suppliers for outsourcing the work
SEMrush

 

design – File parsing in UI Layer or Application Services Layer

Let’s say that I have a list of financial transactions that I need to read in from the file. I want to make the best guess I can at what account should be credited/debited based on the transaction memo compared to past transactions.

For example, if Wal-Mart was used with ‘Shopping’ then if a transaction that gets read in from the file with Wal-Mart as the description should show ‘Shopping’. If there cannot be a match found, then the application should make the best guess and get feedback from the user. If there is not a best match then the user should be asked which account makes most sense.

To me, there is a lot of interaction with the user so it would make sense that this should all live in the UI layer. Once all the transactions are paired with accounts, then it should be sent to the Application Service layer to be saved.

Right now I’m just using a CLI, so I could inject an object that inherits from a ‘Presenter’ interface that the Application Service uses; however, this will not work when I get rid of the CLI and want to use a REST API around the Application Service layer.

Does it make sense to just include all this logic in the UI layer?

amazon web services – How to migrate to Fargate from EC2 in ECS cluster?

I am planning to migrate to Fargate for autoscaling purposes. I already have task definitions for both my staging and production environments which are currently live. There’s two ways I thought I can migrate to Fargate, either create a new Task Definition to use a Fargate and pretty much use the same configuration that my EC2 instance is using. OR, I can export the concerned Task Definition into JSON and replace the values of requiredCompatibilities and compatibilites from EC2 to FARGATE and call it a day, and deploy. Don’t know if that would work? Here’s a sample Task Definition that I have modified to use FARGATE in aforementioned keys. Some redacted data such as environment variables.

{
  "ipcMode": null,
  "executionRoleArn": null,
  "containerDefinitions": [
    {
      "dnsSearchDomains": null,
      "environmentFiles": null,
      "logConfiguration": {
        "logDriver": "awslogs",
        "secretOptions": null,
        "options": {
          "awslogs-group": "/ecs/MY-PROJECT-staging",
          "awslogs-region": "my-region",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "entryPoint": null,
      "portMappings": [
        {
          "hostPort": 8080,
          "protocol": "tcp",
          "containerPort": 8020
        }
      ],
      "command": null,
      "linuxParameters": null,
      "cpu": 0,
      "resourceRequirements": null,
      "ulimits": null,
      "dnsServers": null,
      "mountPoints": [],
      "workingDirectory": null,
      "secrets": null,
      "dockerSecurityOptions": null,
      "memory": 300,
      "memoryReservation": null,
      "volumesFrom": [],
      "stopTimeout": null,
      "image": "$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG",
      "startTimeout": null,
      "firelensConfiguration": null,
      "dependsOn": null,
      "disableNetworking": null,
      "interactive": null,
      "healthCheck": null,
      "essential": true,
      "links": null,
      "hostname": null,
      "extraHosts": null,
      "pseudoTerminal": null,
      "user": null,
      "readonlyRootFilesystem": null,
      "dockerLabels": {
        "env": "staging"
      },
      "systemControls": null,
      "privileged": null,
      "name": "MY-PROJECT-web-stage"
    }
  ],
  "placementConstraints": [],
  "memory": null,
  "taskRoleArn": null,
  "compatibilities": [
    "FARGATE" | Earlier this was EC2
  ],
  "taskDefinitionArn": "task-definition/MY-PROJECT-staging:10",
  "family": "MY-PROJECT-staging",
  "requiresAttributes": [
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.ecr-auth"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
    }
  ],
  "pidMode": null,
  "requiresCompatibilities": [
    "FARGATE" | Earlier this was EC2
  ],
  "networkMode": null,
  "cpu": null,
  "revision": 10,
  "status": "ACTIVE",
  "inferenceAccelerators": null,
  "proxyConfiguration": null,
  "volumes": []
}