3

I am trying to move some C# MVC legacy code into a shared DLL. All went well so far, but I was asked that that shared DLL need not reference System.Web in any way.

The only type used in that DLL from System.Web is HttpPostedFileBase:

public string ChangeAttachment(int userId, HttpPostedFileBase file)
{
    string attachmentsFolderPath = ConfigurationManager.AppSettings["AttachmentsDirectory"];
    if (!Directory.Exists(attachmentsFolderPath))
    {
        Directory.CreateDirectory(attachmentsFolderPath);
    }

    string fileTarget = Path.Combine(attachmentsFolderPath, userId.ToString() + Path.GetExtension(file.FileName));

    if (File.Exists(fileTarget))
    {
        File.Delete(fileTarget);
    }

    file.SaveAs(fileTarget);

    return fileTarget;
}

As you can see, no HTTP or Web functionality is needed here, as only its FileName and SaveAs() members are used.

Is there a substitute that I can easily convert HttpPostedFileBase to it at the caller, so that all I need to pass as a parameter is a non-web file?

Note: HttpPostedFileBase inherits directly from System.Object, not from any file class.

datps
  • 768
  • 1
  • 6
  • 16

2 Answers2

4

HttpPostedFileBase is an abstract class. So the challenge is that you're not actually replacing that class, you're replacing HttpPostedFileWrapper, which is the implementation. (It's not what the class inherits from, it's what inherits from it.)

HttpPostedFileWrapper in turn references other System.Web classes like HttpInputStream and 'HttpPostedFile`.

So you can't replace it. Perhaps by asking you not to reference System.Web the intent was that you were moving legacy code not directly related to web functionality, like business logic. If you can't just leave the code out altogether, perhaps you could leave it out of the new assembly you're creating, and then have another assembly which does reference System.Web. If they don't need this particular functionality they only reference the one assembly, but if they need this then they can also add the second assembly which does reference System.Web.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
  • Thank you. Is there a FileStream constructor that accepts a derivative of `HttpPostedFileWrapper` as its parameter? – datps Mar 28 '16 at 10:48
  • 1
    No. You can look at all of the constructors here: https://msdn.microsoft.com/en-us/library/system.io.filestream(v=vs.110).aspx. (I use the MSDN documentation for classes and methods constantly.) – Scott Hannen Mar 28 '16 at 11:44
1

If you don't want to Reference System.Web and also want to use the SaveAs method, you can define an interface and also a wrapper to make a link. It's not a very simple approach though:

//// Second assembly (Without referencing System.Web):
// An interface to link the assemblies without referencing to System.Web
public interface IAttachmentFile {
    void SaveAs(string FileName);
}
..
..
// Define ChangeAttachment method
public string ChangeAttachment(int userId, IAttachmentFile attachmentFile) { 
   string attachmentsFolderPath = ConfigurationManager.AppSettings["AttachmentsDirectory"];
   if (!Directory.Exists(attachmentsFolderPath)) {
        Directory.CreateDirectory(attachmentsFolderPath);
   }
   string fileTarget = Path.Combine(
        attachmentsFolderPath, 
        userId.ToString() + Path.GetExtension(file.FileName) 
   );
   if (File.Exists(fileTarget)) {
       File.Delete(fileTarget);
   }
   // This call leads to calling HttpPostedFileBase.SaveAs
   attachmentFile.SaveAs(fileTarget);
   return fileTarget;
}

//// First assembly (Referencing System.Web):
// A wrapper class around HttpPostedFileBase to implement IAttachmentFile   
class AttachmentFile : IAttachmentFile {
    private readonly HttpPostedFileBase httpPostedFile;
    public AttachmentFile(HttpPostedFileBase httpPostedFile) {
        if (httpPostedFile == null) {
            throw new ArgumentNullException("httpPostedFile");
        }
        this.httpPostedFile = httpPostedFile;
    }
    // Implement IAttachmentFile interface
    public SaveAs(string fileName) {
        this.httpPostedFile.SaveAs(fileName);
    }
}
..
..
// Create a wrapper around the HttpPostedFileBase object
var attachmentFile = new AttachmentFile(httpPostedFile);

// Call the ChangeAttachment method
userManagerObject.ChangeAttachment(userId, attachmentFile);
Mehrzad Chehraz
  • 5,092
  • 2
  • 17
  • 28
  • Thank you. Unfortunately, an interface does not help me here because what I really need is a **converter** from `HttpPostedFileBase`/`HttpPostedFileWrapper` to a binary serializer, similar to the one described [in this answer](http://stackoverflow.com/a/22417048/5769938) or [this article](http://blog.danskingdom.com/saving-and-loading-a-c-objects-data-to-an-xml-json-or-binary-file/). – datps Mar 28 '16 at 07:44
  • @datps I dont really understand what does your question has to do with binary serializer. You may need to update it for clarification. – Mehrzad Chehraz Mar 28 '16 at 08:00