Appropriate separation of concerns for this case? This is a method that calls a web service, it uploads an audio file and fetches metadata back.

While the advantage is that there is only one method to call there are a few concerns about it :


There is some UI-related code (upload progress)
Some audio-related code (format detection)
Web-service related code (first purpose)


In the end, while it tries to be smart, it's completely tied to a particular audio library, it will report progress anyway and well, it doesn't only upload ...

How would you apply separation of concerns to this current method ?


Would transforming the fileFormat to a parameter be acceptable ?
What about handler, how can it be used without being tied to the upload process ?


I'm not necessarily asking for code, directions to some documentation on the subject is fine too.

public class TrackUpload
{
    public async Task&lt;string&gt; Upload(string apiKey, string path, ProgressEventHandler handler)
    {
        if (apiKey == null) throw new ArgumentNullException("apiKey");
        if (path == null) throw new ArgumentNullException("path");
        using (var stream = new ReadOnlyFileStream(path))
        {
            if (handler != null)
            {
                stream.ProgressChanging += handler;
            }

            string fileFormat = TrackFormatDetector.Detect(path);
            if (fileFormat == null)
            {
                throw new InvalidAudioFormatException();
            }

            var dataContent = new MultipartFormDataContent();
            dataContent.Add(new StringContent(apiKey), "api_key");
            dataContent.Add(new StringContent(fileFormat), "filetype");
            dataContent.Add(new StreamContent(stream), "track");
            var client = new HttpClient();
            client.DefaultRequestHeaders.UserAgent.Add(
                new ProductInfoHeaderValue(new ProductHeaderValue("xxxx", "1.0")));
            HttpResponseMessage response =
                await client.PostAsync(@"http://developer.echonest.com/api/v4/track/upload", dataContent);
            response.EnsureSuccessStatusCode();
            HttpContent content = response.Content;

            if (handler != null)
            {
                stream.ProgressChanging -= handler;
            }

            using (var reader = new StreamReader(await content.ReadAsStreamAsync()))
            {
                string s = await reader.ReadToEndAsync();
                return s;
            }
        }
    }
}
You should move fileFormat to parameters, this method is doing too much
Use IProgress&lt;T&gt; instead of handler to properly report progress back to the UI thread (see Enabling Progress and Cancellation in Async APIs for examples).
Add CancellationToken parameter if necessary