c# - 使用 asp.net web api 和 knockout js 处理图像上传的输入表单

标签 c# entity-framework asp.net-web-api knockout.js

这是我的代码,如有需要,请随意更正

public class Employee
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string ImagePath { get; set; }
    public string Address { get; set; }

    public int DeptId { get; set; }
    public Dept Dept { get; set; }
}

我的种子数据

context.Employees.AddOrUpdate(x => x.EmployeeId,
   new Employee()
   {
       EmployeeId =  1,
       LastName = "Carson",
       FirstName = "Alexander",
       ImagePath = "images/CarsonAlex.png",
       Address = "Brazil",
       DeptId = 2
   },
   new Employee()
   {
       EmployeeId = 2,
       LastName = "Arturo",
       FirstName = "Olivetto",
       ImagePath = "images/ArturoOliva.png",
       Address = "Brazil",
       DeptId = 1
   },
   new Employee()
   {
       EmployeeId = 3,
       LastName = "Alonso",
       FirstName = "Meredith",
       ImagePath = "images/MeredithAlonso.png",
       Address = "Brazil",
       DeptId = 3
   }
);

我的 View 模型类

public class EmployeeDetailVm
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string ImagePath { get; set; }
    public string Address { get; set; }
    public int DeptId { get; set; }
    public string DeptName { get; set; }
}

岗位员工api Controller

[ResponseType(typeof(EmployeeDetailVm))]
public IHttpActionResult PostEmployee(EmployeeDetailVm employees)
{
    var employee = new Employee
    {
        EmployeeId = employees.EmployeeId,
        LastName = employees.LastName,
        FirstName = employees.FirstName,
        ImagePath = employees.ImagePath,
        Address = employees.Address,
        DeptId = employees.DeptId
    };

    if (employees != null)
    {
        // Extract the image from the image string
        string regEx = "data:(.+);base64,(.+)";
        Match match = Regex.Match(employees.ImagePath, regEx);

        if (match.Success)
        {
            // Get the content-type of the file and the content
            string imageType = match.Groups[1].Value;
            string base64Image = match.Groups[2].Value;

            if (imageType != null && base64Image != null)
            {
                // Verify the content-type is an image
                string imageRegEx = "image/(.+)";
                match = Regex.Match(imageType, imageRegEx);
            }

            if (match.Success)
            {
                // Get the file extension from the content-type
                string fileExtension = match.Groups[1].Value;
                // Get the byte-array of the file from the base64 string

                byte[] image = Convert.FromBase64String(base64Image);

                string path = HttpContext.Current.Server.MapPath("~/images");
                string fileName = employees.FirstName + employees.LastName;

                // Generate a unique name for the file (add an index to it if it already exists)                                                        
                string targetFile = fileName + "." + fileExtension;

                int index = 0;
                while (File.Exists(Path.Combine(path, targetFile)))
                {
                    index++;
                    targetFile = fileName + index + "." + fileExtension;
                }

                // Write the image to the target file, and update the agent with the new image path
                File.WriteAllBytes(Path.Combine(path, targetFile), image);
                employees.ImagePath = "images/" + targetFile;

                db.Employees.Add(employee);
                db.SaveChanges();


                employees.EmployeeId = employee.EmployeeId;

                return Ok(employees);

            }

        }
    }

    throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not deserialize Employee"));
}

这是 knockout 的 View 模型

var employeeUrl = "http://localhost:50081/api/employees";
var deptUrl = "http://localhost:50081/api/depts";

var EmployeeViewModel = function () {
    var self = this;
    self.error = ko.observable();

    self.employeeList = ko.observableArray();

    self.listDepts = ko.observableArray();

    self.newEmployee = {
        LastName: ko.observable(),
        FirstName: ko.observable(),
        ImagePath: ko.observable(),
        Address: ko.observable(),
        Dept: ko.observable()
    }


    self.ajaxHelper = function(uri, method, data) {
        self.error('');
        return $.ajax({
            type: method,
            url: uri,
            dataType: 'json',
            contentType: 'application/json',
            data: data ? JSON.stringify(data) : null
        }).error(function(jqXhr, textStatus, errorThrown) {
            self.error(errorThrown + ': ' + jqXhr.responseText);
        });
    },

    self.getDepts = function() {
        self.ajaxHelper(deptUrl, 'GET').done(function (data) {
            self.listDepts(data);
        });
    },

    self.getAllEmployee = function() {
        self.ajaxHelper(employeeUrl, 'GET').done(function(data) {
            self.employeeList(data);
        });
    },

    self.addEmployee = function (formElement) {
        var employee = {
            LastName: self.newEmployee.LastName(),
            FirstName: self.newEmployee.FirstName(),
            ImagePath: self.newEmployee.ImagePath(),
            Address: self.newEmployee.Address(),
            DeptId: self.newEmployee.Dept().DeptId
        };

        self.ajaxHelper(employeeUrl, 'POST', employee).done(function (item) {
            self.employeeList.push(item);
        });
    }

};

$(document).ready(function() {
    var employeeVm = new EmployeeViewModel();
    ko.applyBindings(employeeVm);
    employeeVm.getAllEmployee();
    employeeVm.getDepts();
});

这是我在简单的 html 表格上的显示,效果很好

<div class="col-md-6">
    <div class="panel panel-default">
        <div class="panel-heading">
            <h2 class="panel-title">Authors</h2>
        </div>
        <div class="panel-body">
            <table class="table table-striped ">
                <thead>
                <tr>
                    <th>Employee Photo </th>
                    <th>Last Name</th>
                    <th>First Name </th>
                    <th>Dept Name </th>
                </tr>
                </thead>
                <tbody data-bind="foreach: employeeList">
                <tr>
                    <td>
                        <img data-bind="attr:{ src: ImagePath}" width="75" height="75"/>
                    </td>
                    <td data-bind="text: LastName"></td>
                    <td data-bind="text: FirstName"></td>
                    <td data-bind="text: DeptName"></td>
                </tr>
                </tbody>
            </table>

        </div>
    </div>
</div>

最后是添加表单,

<div class="col-md-6">
    <form class="form-horizontal" data-bind="submit: addEmployee" enctype="multipart/form-data">
        <div class="form-group">
            <label class="col-sm-4 control-label">Dept Name</label>
            <div class="col-sm-8">
                <select class="form-control" data-bind="options:listDepts, optionsText: 'DeptName', value: newEmployee.Dept"></select>
            </div>
        </div>

        <div class="form-group" data-bind="with: newEmployee">
            <label for="inputLastName" class="col-sm-4 control-label">Last Name</label>
            <div class="col-sm-8">
                <input type="text" class="form-control" id="inputLastName" data-bind="value:LastName"/>
            </div>

            <label for="inputFirstName" class="col-sm-4 control-label">First Name</label>
            <div class="col-sm-8">
                <input type="text" class="form-control" id="inputFirstName" data-bind="value:FirstName"/>
            </div>

            <label for="inputImagePath" class="col-sm-4 control-label">Upload Photo</label>
            <div class="col-sm-8">
                <input type="file" class="form-control" id="inputImagePath" data-bind="value:ImagePath"/>
            </div>

            <label for="inputAddress" class="col-sm-4 control-label">Address</label>
            <div class="col-sm-8">
                <input type="text" class="form-control" id="inputAddress" data-bind="value:Address"/>
            </div>
        </div>
        <div class="col-md-offset-4 col-md-8">
            <button type="submit" class="btn btn-default">Submit</button>
        </div>
    </form>
</div>

在我的浏览器控制台中出现以下错误

发布 http://localhost:50081/api/employees 400(错误请求)

我相信错误可能源于代码行

<input type="file" class="form-control" id="inputImagePath" data-bind="value:ImagePath" />

我是 knockout 的新手,他们的网站上没有太多帮助的文档,

最佳答案

您需要更新您对图像/文件输入的绑定(bind)

<input type="file" 
       class="form-control" 
       id="inputImagePath" 
       data-bind="fileSrc: ImagePath" 
       accept="image/*">

您可以使用自定义绑定(bind)处理程序来管理将发送到 Controller 的文件数据

ko.bindingHandlers.fileSrc = {
    init: function (element, valueAccessor) {
        ko.utils.registerEventHandler(element, "change", function () {
            var reader = new FileReader();

            reader.onload = function (e) {
                var value = valueAccessor();
                value(e.target.result);
            }
            // Read in the image file as a data URL.
            reader.readAsDataURL(element.files[0]);
        });
    }
};

鉴于我不知道您的路由是如何配置的,我相信根据您的操作名称 PostEmployee,如果您将 API 路由配置为使用基于默认约定的路由,那么操作将映射到 api/employees/PostEmployee

您的 knockout 代码正试图发布到...

var employeeUrl = "http://localhost:50081/api/employees";

您可以更改帖子的 url 以匹配操作名称或编辑您的 Controller 操作以遵循默认约定...

public class EmployeesController: ApiController {

    [HttpPost]
    [ResponseType(typeof(EmployeeDetailVm))]
    public IHttpActionResult Post(EmployeeDetailVm employees){...}

}

关于c# - 使用 asp.net web api 和 knockout js 处理图像上传的输入表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36529398/

相关文章:

c# - 如果输入几乎相同,我该如何检查?

c# - 如何获取 EF 查询来编译最优化的 SQL?

c# - 使用 EF Core 加载和保存内存中 SQLite 数据库

javascript - 为什么我无法通过 AngularJS POST 向我的 Web Api 发送帖子?

php - 脚本添加不起作用

c# - 如何使用 XmlReader 读取列表中的数据第 2 部分

java - 用于生成 C# 代码的 XML 语法

c# - 枚举和字典<枚举, Action >

c# - 什么是最好的 MVC3 解决方案结构?

asp.net - 完全替换 Swashbuckle UI