2011-10-18 164 views
1

我试图将旧的ASP.NET应用程序转换为MVC(我刚刚学习MVC)。我需要在GridView中显示图像。图像本身作为数据类型图像存储在SQL Server表中。以前使用的代码如下所示。有人可以建议使用MVC的方法吗?我正在考虑创建一个可以嵌入标准视图的部分页面,但不确定这是否是正确的设计。从数据库中读取图像并在视图中显示

谢谢!

` string sqlText = "SELECT * FROM Images WHERE img_pk = " + id; 
     SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString); 

     SqlCommand command = new SqlCommand(sqlText, connection); 
     connection.Open(); 
     SqlDataReader dr = command.ExecuteReader(); 
     if (dr.Read()) 
     { 
      //Response.Write("test"); 
      Response.BinaryWrite((byte[])dr["img_data"]); 
     } 
     connection.Close(); 
    } 

那么就可以使用此图像标记被引用:

<asp:Image Height="73" Width="80" ID="Image1" ImageAlign="Middle" ImageUrl='<%#"viewimage.aspx?id=" + Eval("ImageId") %>' runat="server"/></a></td> 
+0

代码是动作方法,Image控件是图片标签,ImageUrl是图片标签的动作url。有点。 – bzlm

回答

7

的第一件事就是约在GridView的ASP.NET MVC应用程序忘记。服务器端控件,回发,视图状态,事件......所有这些都是不再存在的概念。

在ASP.NET MVC中,您可以使用模型,控制器和视图。

所以,你可以写一个控制器动作将从数据库中获取的图像,并为它服务:

public class ImagesController: Controller 
{ 
    public ActionResult Index(int id) 
    { 
     string sqlText = "SELECT img_data FROM Images WHERE img_pk = @id"; 
     using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString)) 
     using (var command = conn.CreateCommand()) 
     { 
      conn.Open(); 
      command.CommandText = sqlText; 
      command.Parameters.AddWithValue("@id", id); 
      using (var reader = command.ExecuteReader()) 
      { 
       if (!reader.Read()) 
       { 
        return HttpNotFound(); 
       } 

       var data = GetBytes(reader, reader.GetOrdinal("img_data")); 
       return File(data, "image/jpg"); 
      } 
     } 
    } 

    private byte[] GetBytes(IDataReader reader, int columnIndex) 
    { 
     const int CHUNK_SIZE = 2 * 1024; 
     byte[] buffer = new byte[CHUNK_SIZE]; 
     long bytesRead; 
     long fieldOffset = 0; 
     using (var stream = new MemoryStream()) 
     { 
      while ((bytesRead = reader.GetBytes(columnIndex, fieldOffset, buffer, 0, buffer.Length)) > 0) 
      { 
       byte[] actualRead = new byte[bytesRead]; 
       Buffer.BlockCopy(buffer, 0, actualRead, 0, (int)bytesRead); 
       stream.Write(actualRead, 0, actualRead.Length); 
       fieldOffset += bytesRead; 
      } 
      return stream.ToArray(); 
     } 
    } 
} 

,然后在你看来简单:

<img src="@Url.Action("Index", "Images", new { id = "123" })" alt="" /> 

现在当然这一切的控制器行动是很好,花花公子,但你应该真正抽象所有数据访问到存储库:

public interface IImagesRepository 
{ 
    byte[] GetImageData(int id); 
} 

然后实现您所使用的数据提供这个方法:

public class ImagesRepositorySql: IImagesRepository 
{ 
    public byte[] GetImageData(int id) 
    { 
     // you already know what to do here. 
     throw new NotImplementedException(); 
    } 
} 

最后你将你的控制器成为数据库无关。在应用程序层,现在弱它们之间的耦合,这将允许重复使用和单元测试他们在隔离:

public class ImagesController: Controller 
{ 
    private readonly IImagesRepository _repository; 
    public ImagesController(IImagesRepository repository) 
    { 
     _repository = repository; 
    } 

    public ActionResult Index(int id) 
    { 
     var data = _repository.GetImageData(id); 
     return File(data, "image/jpg"); 
    } 
} 

和最后一部分是配置你喜欢的DI框架注入库的正确实施进入控制器。

+0

+1教学IoC和Repository模式回答无辜图像显示问题:D – rouen

+0

感谢您的回复Darin!我插入你的代码,它没有太多修改。我现在需要更好地理解它。我不喜欢仅仅使用代码示例而不知道它是如何工作的。 – Marcusg

相关问题