【问题标题】:How to send and display image from view to controller?如何将图像从视图发送和显示到控制器?
【发布时间】:2020-09-03 23:04:21
【问题描述】:

我的项目有两个控制器:mvc 和 api。图像已成功从视图传递到 mvc 控制器,问题是如何将其从 mvc 控制器发送到 api 控制器?

 [HttpPost]
    public IActionResult Create(ProductSubCategoryviewmodel productSubCategory)
    {
        if (ModelState.IsValid)
        {
            string uniqueFileName = UploadedFile(productSubCategory);
                ProductSubCategoryviewmodel category = new ProductSubCategoryviewmodel();
            {
                category.ProductSubCategoryName = productSubCategory.ProductSubCategoryName;
                category.Rate = productSubCategory.Rate;
                category.DisplayOrder = productSubCategory.DisplayOrder;
                category.Image = uniqueFileName;
            };               
        }

        HttpClient client = api.FromApi();
        var prosubjson = JsonConvert.SerializeObject(productSubCategory);
        var buffer = Encoding.UTF8.GetBytes(prosubjson);
        var byteContent = new ByteArrayContent(buffer);
        byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        try
        {
            var result = client.PostAsync("api/ProductSubCategories", byteContent).Result;
            // TODO: Add insert logic here
            return RedirectToAction(nameof(Index));
        }
        catch
        {
            return View();
        }
    }

    private string UploadedFile(ProductSubCategoryviewmodel productSubCategory)
    {
        string uniqueFileName = null;

        if (productSubCategory.Image != null)
        {
            string uploadsFolder = Path.Combine(hostEnvironment.WebRootPath, "Images");
            uniqueFileName = Guid.NewGuid().ToString() + "_" + productSubCategory.Image;
            string filePath = Path.Combine(uploadsFolder, uniqueFileName);
            using (var fileStream = new FileStream(filePath, FileMode.Create))
            {
                productSubCategory.Image.CopyTo(fileStream);
            }
        }
        return uniqueFileName;
    }

显示错误:没有给出与“string.CopyTo(int, char[], int, int)”所需的形式参数“destination”相对应的参数。强调文本

【问题讨论】:

  • 为什么需要将其传递给 API 控制器?如果原因是你想重用 API 控制器中的逻辑,也许你可以创建一个服务层来代替你的 API 和 MVC 控制器使用。
  • 感谢您的建议,您能帮我发送示例代码吗?
  • 您可以查看我的帖子答案。

标签: asp.net-mvc asp.net-core asp.net-core-webapi


【解决方案1】:

为了简单起见,只是为了给出一个想法,它可以是这样的。

public class MyService
{
    public void MyTestMethod()
    {
        // Logic code here
    }
}

public class MyApiController : Controller
{
    public IActionResult MyApiMethod()
    {
        MyService myService = new MyService();
        myService.MyTestMethod();
    }
}

public class MyMVCController : Controller
{
    public IActionResult MyMVCMethod()
    {
        MyService myService = new MyService();
        myService.MyTestMethod();
    }
}

【讨论】:

  • 有两个不同的项目,一个在mvc,另一个在api
【解决方案2】:

如何将图像从视图发送和显示到控制器?

根据您的代码,我想您正在使用 IFormFile 将图像从视图发送到控制器,但我不确定您使用哪种 DataType 存储在数据库中,base64 字符串或字节数组。在我看来,我更喜欢使用字节数组来存储上传文件。

更多详细信息,请查看以下代码:

模型中的代码:

public class Movie
{
    public int Id { get; set; }
    public string Title { get; set; }

    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }
    public string Genre { get; set; }
    public decimal Price { get; set; }

    [MaxLength]
    public byte[] Poster { get; set; }
}

和视图模型(使用此视图模型将文件上传到控制器)

public class MovieViewModel
{
    [Key]
    public int RowNumber { get; set; }

    public string Title { get; set; }

    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }
    public string Genre { get; set; }
    public decimal Price { get; set; } 
    [NotMapped]
    public IFormFile PosterImage { get; set; }
}

控制器中的代码:

  // GET: Movies/Create
    public IActionResult Create()
    {
        return View();
    }

    // POST: Movies/Create 
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(MovieViewModel model)
    {
        if (ModelState.IsValid)
        { 
            Movie movie = new Movie
            {
                Title = model.Title,
                Genre = model.Genre,
                ReleaseDate = model.ReleaseDate,
                Price = model.Price,
            };
            if (model.PosterImage != null)
            { 
                using (var target = new MemoryStream())
                {
                    model.PosterImage.CopyTo(target);
                    movie.Poster = target.ToArray(); //get the image byte array
                }
            }
            _context.Add(movie);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(model);
    }

Index 视图中的代码(使用 Movie 模型,而不是 MovieViewModel):

使用&lt;img&gt;标签显示图片。

@model IEnumerable<dotNetCore3_1.Models.Movie>
 
<table class="table">
    <thead>
        <tr>
            ...
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            ...
            <td>
                @if (item.Poster != null)
                {

                    <img class="img-responsive  " style="width:50px; height:50px" src="data:image/jpeg;base64,@Convert.ToBase64String(item.Poster)" />
                }
                else
                {
                    <img class="img-responsive " style="width:50px; height:50px" src="~/images/default.jpg" />
                } 
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
                <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

如何将它从 mvc 控制器发送到 api 控制器?

要从 MVC 控制器向 API 操作方法发送数据,您可以使用 HttpClient() 方法,并将对象 json 字符串传输到 API 控制器。像这样的代码:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(MovieViewModel model)
    {
        if (ModelState.IsValid)
        { 
            Movie movie = new Movie
            {
                Title = model.Title,
                Genre = model.Genre,
                ReleaseDate = model.ReleaseDate,
                Price = model.Price,
            };
            if (model.PosterImage != null)
            { 
                using (var target = new MemoryStream())
                {
                    model.PosterImage.CopyTo(target);
                    movie.Poster = target.ToArray(); //stored the image using byte array.
                }
            }
            //consume the webapi and post the model.
            using (var client = new HttpClient())
            {
                var requesturi = "https://localhost:44334/api/MoviesAPI";
                StringContent content = new StringContent(JsonConvert.SerializeObject(movie), Encoding.UTF8, "application/json");

                //HTTP POST
                var postTask = client.PostAsync(requesturi, content);
                postTask.Wait();

                var result = postTask.Result;
                if (result.IsSuccessStatusCode)
                {
                    return RedirectToAction("Index");
                }
            }

            //_context.Add(movie);
            //await _context.SaveChangesAsync();
            //return RedirectToAction(nameof(Index));
        }
        return View(model);
    }

API 控制器方法中的代码:

    // POST: api/MoviesAPI
    // To protect from overposting attacks, enable the specific properties you want to bind to, for
    // more details, see https://go.microsoft.com/fwlink/?linkid=2123754.
    [HttpPost]
    public async Task<ActionResult<Movie>> PostMovie(Movie movie)
    {
        _context.Movie.Add(movie);
        await _context.SaveChangesAsync();

        return CreatedAtAction("GetMovie", new { id = movie.Id }, movie);
    }

最后截图如下:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多