0

UI

<input type = "file" title="Please upload some file" name="file" />

MVC

/*below method is called from a MVC controller 
 this method resides for now in MVC project itself*/
public IEnumerable<CustomerTO> FetchJson(HttpPostedFile file)
    {
        using (StreamReader sr = new StreamReader(file.FileName))
        {
            {
                file.saveAs("details.txt");
                string json = sr.ReadToEnd();
                IEnumerable<CustomerTO> customers=
                    JsonConvert.DeserializeObject<List<CustomerTO>>(json);
               return customers; 
            }
        }
    }

When the above method in MVC project or some kind of web based project, all references are find fine.

But I am thinking to create a utility class to handle all such operations. So I created a class library project & added a class Utitlity.cs

Class Library

public IEnumerable<CustomerTO> FetchJson(HttpPostedFile file)
    {
        //but HttpPostedFile is throwing error.
        //NOTE Ideally,I shouldn't be saving the posted file
    }

Now I know FileUpload is UI control HttpPostedFile handles all operations related to this.

I can easily add reference using System.Web but I doubt if that's right??

But how do I address my requirement then without any kind of overhead?? Memory allocation, execution & all such is very critical

Kgn-web
  • 7,047
  • 24
  • 95
  • 161
  • Not quite sure how you can claim the first works - your file input does not have a `name` attribute so the parameter will be `null`. And how are you calling the 2nd 'utility' method - you still need an action method in your `Controller` to receive the request. –  Jul 29 '17 at 07:02
  • @StephenMuecke, Sorry!! added the missing details – Kgn-web Jul 29 '17 at 07:09
  • It would need to be `name="file"` to bind to a parameter `HttpPostedFile file` :) –  Jul 29 '17 at 07:14
  • @StephenMuecke, that also corrected. Thanks :) – Kgn-web Jul 29 '17 at 07:16
  • You still need to controller method, but inside it you can just call `return yourUtilityAssemby.FetchJson(file);` but I suggest you rename one or the other to avoid confusion (and allow you to include a `using` statement in the controller –  Jul 29 '17 at 07:20

1 Answers1

1

Read this answer once you make sure that controller method receives posted file reference properly.

You don't need to add System.Web reference in class library. Instead just pass file contents to refactored method. Moreover since you are making a utility class, make sure it can return any type of DTO and not just CustomerDTO. You should be able to use the same class/ method, if you ever need to pass in Accounts file and get AccountDTOs out of it, for example.

In fact, you should be able to use that code for deserializing any string content to any type you want. You could use Generics here.

// Controller.cs
public IEnumerable<CustomerTO> FetchJson(HttpPostedFile file) 
{
    string fileContent;
    using (StreamReader sr = new StreamReader(file.FileName)) {
        file.saveAs("details.txt");
        fileContent = sr.ReadToEnd();
    }

    var customers = JsonSerializer.Deserialize<List<CustomerTO>>(content); // Refactored

    return customers; 
}

// JsonSerializer.cs
public static T Deserialize<T>(string content) {
    // ...
    return JsonConvert.DeserializeObject<T>(content);
}

Reading file content using StreamReader in Controller need not be refactored. That's unnecessary IMO.

Nikhil Vartak
  • 5,002
  • 3
  • 26
  • 32
  • Great. But as I mentioned saving file is overhead to me – Kgn-web Jul 29 '17 at 07:30
  • Sure. User uploads file, need to read the content, Deserialize & do some operation( ex return to UI) That's it. If user uploads hundreds of files saving that many files isn't overhead – Kgn-web Jul 29 '17 at 07:35
  • If you don't want copy of uploaded file then don't save it. Instead use `file.InputStream`. Also you did not talk about possibility of multiple file uploads in you question. Make sure you clearly indicate actual scenario in question. – Nikhil Vartak Jul 29 '17 at 07:41