【问题标题】:Using a controller with WEB API Routing使用带有 WEB API 路由的控制器
【发布时间】:2020-04-08 03:14:36
【问题描述】:

在我的项目(Asp.net MVC)中,我想使用 DevExtreme GridView 来显示我的数据。我首先使用代码来创建数据库和表。在项目中,我有一个名为 Member 的模型。我确实右键单击 Controller 文件夹并选择 Add->Controller->DevExtreme Web API Controller with actions,使用实体框架。在向导中,我选择了我的数据库上下文和模型并确定了我的控制器名称 (MembersController),然后单击了添加。所以在 Views 文件夹中,我创建了一个名为 Members 的文件夹,并在其中添加了一个名为 Index 的视图。 (我不知道视图的确切名称必须是什么,您认为是索引)。在索引视图中,我使用向导添加了一个 DevExtreme GridView(右键单击视图上下文,然后单击 Insert A DevExtreme Control Here。在向导中,我选择了 GridView 作为控件和 DatabaseContext、Member 模型和 Members 控制器。你可以在下面看到我的所有代码: 会员模式: 型号:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace WebApplication2.Models
{
    public class Member
    {
        #region Ctor
        public Member()
        {

        }
        #endregion

        #region Properties

        [Key]
        public int MemberID { get; set; }

        [Required(ErrorMessage ="*")]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "*")]
        public string LastName { get; set; }

        public string  Phone { get; set; }

        public string Mobile { get; set; }

        [Required(ErrorMessage = "*")]
        public string NID { get; set; }

        [Required(ErrorMessage = "*")]
        public string MID { get; set; }

        [Required(ErrorMessage = "*")]
        public string SalaryID { get; set; }
        #endregion
    }
}

控制器:

[Route("api/Members/{action}", Name = "MembersApi")]
public class MembersController : ApiController
{
    private ApplicationDbContext _context = new ApplicationDbContext();

    [HttpGet]
    public HttpResponseMessage Get(DataSourceLoadOptions loadOptions) {
        var members = _context.Members.Select(i => new {
            i.MemberID,
            i.FirstName,
            i.LastName,
            i.Phone,
            i.Mobile,
            i.NID,
            i.MID,
            i.SalaryID
        });
        return Request.CreateResponse(DataSourceLoader.Load(members, loadOptions));
    }

    [HttpPost]
    public HttpResponseMessage Post(FormDataCollection form) {
        var model = new Member();
        var values = JsonConvert.DeserializeObject<IDictionary>(form.Get("values"));
        PopulateModel(model, values);

        Validate(model);
        if (!ModelState.IsValid)
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, GetFullErrorMessage(ModelState));

        var result = _context.Members.Add(model);
        _context.SaveChanges();

        return Request.CreateResponse(HttpStatusCode.Created, result.MemberID);
    }

    [HttpPut]
    public HttpResponseMessage Put(FormDataCollection form) {
        var key = Convert.ToInt32(form.Get("key"));
        var model = _context.Members.FirstOrDefault(item => item.MemberID == key);
        if(model == null)
            return Request.CreateResponse(HttpStatusCode.Conflict, "Member not found");

        var values = JsonConvert.DeserializeObject<IDictionary>(form.Get("values"));
        PopulateModel(model, values);

        Validate(model);
        if (!ModelState.IsValid)
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, GetFullErrorMessage(ModelState));

        _context.SaveChanges();

        return Request.CreateResponse(HttpStatusCode.OK);
    }

    [HttpDelete]
    public void Delete(FormDataCollection form) {
        var key = Convert.ToInt32(form.Get("key"));
        var model = _context.Members.FirstOrDefault(item => item.MemberID == key);

        _context.Members.Remove(model);
        _context.SaveChanges();
    }


    private void PopulateModel(Member model, IDictionary values) {
        string MEMBER_ID = nameof(Member.MemberID);
        string FIRST_NAME = nameof(Member.FirstName);
        string LAST_NAME = nameof(Member.LastName);
        string PHONE = nameof(Member.Phone);
        string MOBILE = nameof(Member.Mobile);
        string NID = nameof(Member.NID);
        string MID = nameof(Member.MID);
        string SALARY_ID = nameof(Member.SalaryID);

        if(values.Contains(MEMBER_ID)) {
            model.MemberID = Convert.ToInt32(values[MEMBER_ID]);
        }

        if(values.Contains(FIRST_NAME)) {
            model.FirstName = Convert.ToString(values[FIRST_NAME]);
        }

        if(values.Contains(LAST_NAME)) {
            model.LastName = Convert.ToString(values[LAST_NAME]);
        }

        if(values.Contains(PHONE)) {
            model.Phone = Convert.ToString(values[PHONE]);
        }

        if(values.Contains(MOBILE)) {
            model.Mobile = Convert.ToString(values[MOBILE]);
        }

        if(values.Contains(NID)) {
            model.NID = Convert.ToString(values[NID]);
        }

        if(values.Contains(MID)) {
            model.MID = Convert.ToString(values[MID]);
        }

        if(values.Contains(SALARY_ID)) {
            model.SalaryID = Convert.ToString(values[SALARY_ID]);
        }
    }

    private string GetFullErrorMessage(ModelStateDictionary modelState) {
        var messages = new List<string>();

        foreach(var entry in modelState) {
            foreach(var error in entry.Value.Errors)
                messages.Add(error.ErrorMessage);
        }

        return String.Join(" ", messages);
    }

    protected override void Dispose(bool disposing) {
        if (disposing) {
            _context.Dispose();
        }
        base.Dispose(disposing);
    }
}

查看:

   @{
       Layout = "~/Views/Shared/_Layout.cshtml";
    }


    @(Html.DevExtreme().DataGrid<WebApplication2.Models.Member>()
        .DataSource(ds => ds.WebApi()
            .RouteName("MembersApi")
            .LoadAction("Get")
            .InsertAction("Post")
            .UpdateAction("Put")
            .DeleteAction("Delete")
            .Key("MemberID")
        )
        .RemoteOperations(true)
        .Columns(columns => {

            columns.AddFor(m => m.MemberID);

            columns.AddFor(m => m.FirstName);

            columns.AddFor(m => m.LastName);

            columns.AddFor(m => m.Phone);

            columns.AddFor(m => m.Mobile);

            columns.AddFor(m => m.NID);

            columns.AddFor(m => m.MID);

            columns.AddFor(m => m.SalaryID);
        })
        .Editing(e => e
            .AllowAdding(true)
            .AllowUpdating(true)
            .AllowDeleting(true)
        )
    )

WebApiConfig.cs 文件:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Http;

    namespace WebApplication2
    {
        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                config.MapHttpAttributeRoutes();

                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );

                // WebAPI when dealing with JSON & JavaScript!
                // Setup json serialization to serialize classes to camel (std. Json format)
                var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
                formatter.SerializerSettings.ContractResolver =
                    new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
            }
        }
    }

Global.asax.cs 文件:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http;
    using System.Web.Mvc;
    using System.Web.Optimization;
    using System.Web.Routing;

    namespace WebApplication2
    {
        public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {

                AreaRegistration.RegisterAllAreas();
                GlobalConfiguration.Configure(WebApiConfig.Register);
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
            }
        }
    }

此外,我已经根据link 安装了该项目的所有要求。 但是当我尝试使用https://localhost:44328/Members/index RUL 显示视图时,我收到了这个错误:

找不到资源。 说明:HTTP 404。您要查找的资源(或其依赖项之一)可能已被删除、名称已更改或暂时不可用。请检查以下 URL 并确保其拼写正确。

请求的 URL:/Members/index

我尝试了很多方法来纠正我的错误,但我找不到解决方案。我几乎阅读了所有关于路由的文档(mvc 和 web api),但大约 5 天后我仍然无法解决它。 非常感谢您回答我。

【问题讨论】:

  • 请帮忙。我还是解决不了这个问题

标签: asp.net-mvc asp.net-web-api model-view-controller asp.net-mvc-routing asp.net-web-api-routing


【解决方案1】:

据我所知,您收到 404 的原因之一是您似乎没有在任何地方添加参数。除此之外,您的“DataSourceLoadOptions loadOptions”不应用作参数,因为它可能太复杂了。你不应该创建一个服务来检索你的 loadOptions 而不是你提供它吗?

如果您希望所有成员不提供信息,那么您应该这样做。不要为请求提供一些它不知道的元数据。

我建议您执行以下操作:

  1. 创建不需要元数据的 API,例如如何获取数据源。诸如 Members.LastName 之类的内容是可以接受的
  2. 确保首先创建一个负责获取数据的服务。这意味着还需要删除控制器中的所有额外代码并将其放置在更合适的位置。
  3. 保持课堂简洁明了。你的控制器现在有太多的责任。

希望这会有所帮助。如果您在没有“DataSourceLoadOptions loadOptions”参数的情况下按原样尝试 API GET 方法,那么您的 API 将不会返回 404。

【讨论】:

  • 嗨,很遗憾,我没有做对。我更改了 Get 操作,使其没有 LoadOption 参数,但我仍然没有收到答案。非常感谢您根据代码更准确地给出答案。抱歉我的回复晚了。
  • 同时,您可以从这里下载我的项目作为 RAR 文件:drive.google.com/file/d/1o7cTLaYlh4WVRTzcepcpVR8p4cGjc34B/…
【解决方案2】:

由于你没有输入你的 ajax 调用 url,我将不得不处理这个

请求的 URL:/Members/index

这是个问题,你的 webApi 默认路由要求你的 URL 前加/api/

所以这样的事情应该可以工作/api/Members,因此您可以删除该 URL 的 Index 部分,因为请求类型将处理执行 ActionHTTPGet/HTTPPost

编辑:将此用作您的路线

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { controller = "Members" id = RouteParameter.Optional }
);

【讨论】:

  • 嗨@AbdulG,感谢您的重播。不幸的是,在使用api/Members/ 之后,我得到了这个错误:这个 XML 文件似乎没有任何与之关联的样式信息。文档树如下所示。 &lt;Error&gt; &lt;Message&gt; No HTTP resource was found that matches the request URI 'https://localhost:44328/api/Members'. &lt;/Message&gt; &lt;MessageDetail&gt; No action was found on the controller 'Members' that matches the request. &lt;/MessageDetail&gt; &lt;/Error&gt;
猜你喜欢
  • 1970-01-01
  • 2015-05-04
  • 2020-01-04
  • 1970-01-01
  • 2015-05-13
  • 1970-01-01
  • 2021-07-18
  • 1970-01-01
  • 2017-09-18
相关资源
最近更新 更多