如何创建一个可以被其他控制器访问的方法,但它不能用于HttpGet也不能用于HttpPost

时间:2015-02-09 18:43:56

标签: c# asp.net-mvc-5 download

我在我的Controller中创建了一个方法,该方法从html字符串返回一个doc文件。

public class MyController : Controller {

    private FileContentResult Html2DocxResult(string html, string fileDownloadName) {
        byte[] docBytes = DocumentExport.Html2Docx(html);

        FileContentResult result;
        using (var ms = new MemoryStream(docBytes)) {
            result = this.File(ms.ToArray(), "application/msword", fileDownloadName + ".docx");
        }
        return result;
    }
}

当我需要将文件发送到客户端时,我可以这样使用:

public class MyController : Controller {

    [HttpPost]
    public FileContentResult GenerateDocument(string fileName) {
        string html = "<h1>Title</h1><p>Content goes here!</p>";
        return Html2DocxResult(html, fileName);
    }

}

问题是我想在我想要的任何控制器中调用Html2DocxResult。我认为将方法公之于众并不是一种好的做法,因为通过这种方式,我将创建一个我不想存在的可访问的Action。例如,用户可以拨打http://mywebsite.com/MyController/Html2DocxResult?hml=<p>test</p>&fileDownloadName=MyTest,我不想要这个。

我尝试创建一个类,让Html2DocxResult像静态方法一样为所有控制器提供服务。像那样:

namespace BancoQuestoesMVC.Utils {
    public class DocumentExport {
        public static FileContentResult Html2DocxResult(string html, string fileDownloadName) {
            byte[] docBytes = DocumentExport.Html2Docx(html);

            FileContentResult result;
            using (var ms = new MemoryStream(docBytes)) {
                result = Controller.File(ms.ToArray(), "application/msword", fileDownloadName + ".docx");
            }
            return result;
        }
    }
}

但是在这种情况下无法访问方法Controller.File。 我可以将当​​前的Controller作为参数传递给Html2DocxResult并调用callerController.File,问题就解决了。但对我来说这似乎不是一个好习惯。

有人知道如何解决这类问题吗?是否有适合的设计模式? 非控制器类如何具有返回ActionResult但不调用Controller的方法。这个想法是一个概念问题吗?

2 个答案:

答案 0 :(得分:1)

尝试基类。所有需要FileContentResult方法的控制器都可以从这个基类继承。

基类:

public class MyBaseController : Controller {

    protected FileContentResult Html2DocxResult(string html, string fileDownloadName) {
        byte[] docBytes = DocumentExport.Html2Docx(html);

        FileContentResult result;
        using (var ms = new MemoryStream(docBytes)) {
            result = this.File(ms.ToArray(), "application/msword", fileDownloadName + ".docx");
        }
        return result;
    }
}

您的控制器:

public class MyController : MyBaseController {

    [HttpPost]
    public FileContentResult GenerateDocument(string fileName) {
        string html = "<h1>Title</h1><p>Content goes here!</p>";
        return Html2DocxResult(html, fileName);
    }

}

另请注意NonAction属性以及您希望阻止从http Disable action method from being called from the address bar

访问的方法

答案 1 :(得分:1)

另一种解决方案是编写一个从Controller继承的抽象基类,使得Html2DocxResult可以作为受保护的方法访问。所有想要使用它的控制器都必须从这个类继承。

public abstract class Html2DocxController : Controller // please find a better name.
{
    protected FileContentResult Html2DocxResult(string html, string fileDownloadName) 
    {
        byte[] docBytes = DocumentExport.Html2Docx(html);

        FileContentResult result;
        using (var ms = new MemoryStream(docBytes)) 
        {
            result = this.File(ms.ToArray(), "application/msword", fileDownloadName + ".docx");
        }
        return result;
    }
}