2017-11-18 94 views
0

我是MVC中的web应用程序的新手。在过去的两天里,我研究并尝试了很多东西,但没有一个适用于我;我使用ApiController,而不是控制器,所以我不能做像“返回视图(模型)”的东西。如何使用从Api控制器中的GET方法返回的IEnumerable填充DropDownList?

如果你能帮助我理解如何将这些东西连接在一起或显示我的问题在哪里将非常感谢!

情况: 我想制作一个具有级联下拉列表的网络应用程序;第一个选择汽车制造商名单,第二个名单显示所选制造商的汽车型号。列表和提交按钮将在AJAX表单中。

问题: 我只是想知道,我怎么能填充第一个下拉页面加载列表,用我的ApiController一个GET方法返回的汽车制造一个IEnumerable? 然后我可以从那里去。请记住,稍后我将有第二个下拉列表根据第一个下拉列表填充/更新,因此我希望下拉列表的填充位置在客户端完成。

我试了一下:

  1. 使用HTML.DropDownListFor创建列表,但 HTML.DropDownListFor总是得到“未将对象引用设置到对象的实例 ”。我也使用Ajax.BeginForm,但不知道 是否可以实际调用返回IEnumerable的GET方法,并将其添加到 列表中。
  2. 使用$(document).ready()来使用getJSON来获取从我的 ApiController方法获得的汽车,但getJSON不会触发。

我可能在某个地方发生了很大的错误,因为我无法获得任何东西来填充我的列表,而且我仍在学习。非常感谢您的帮助!我现在将显示我的代码,以及我尝试过的一些替代代码。


首先是我的模型类:

public class Make 
    { 
     public int MakeId { get; set; } 
     public string MakeName { get; set; } 
    } 

    public class Model 
    { 
     public int ModelId { get; set; } 
     public string ModelName { get; set; } 
     public int MakeId { get; set; } 
    } 

    public class MakeViewModel 
    { 
     public int SelectedMakeId { get; set; } 
     public IEnumerable<Make> MakesList { get; set; } 
    } 

这里是我的两个GET方法,使()和模式(INT makeID),每个返回IEnumerable的车辆ApiController。他们最终会从本地xml中消费,但现在为了简单起见,我将其删除,每个只返回一个Make或Model项目的列表。

public class VehicleController : ApiController 
{ 
    [System.Web.Http.HttpGet] 
    public IEnumerable<Make> Makes() 
    { 
     List<Make> makesList = new List<Make>(); 

     //Code for consuming from xml file will go here 

     //For now, add one test make to the list 
     Make maketest = new Make(); 
     maketest.MakeId = 1; 
     maketest.MakeName = "MakeTest"; 
     makesList.Add(maketest); 

     //return List of the one test make 
     return makesList; 
    } 

    [System.Web.Http.HttpGet] 
    public IEnumerable<Model> Models(int id) 
    { 
     List<Model> modelsList = new List<Model>(); 

     //Code for consuming from xml file will go here 

     //For now, add one test model to the list 
     Model modeltest = new Model(); 
     modeltest.ModelId = 1; 
     modeltest.ModelName = "ModelTest"; 
     modeltest.MakeId = 1; 
     modelsList.Add(modeltest); 

     //return List of the one test model 
     return modelsList; 
    } 
} 

这是我的Index.cshtml,它加载_Form.cshtml

<h2>Vehicle Selector</h2> 
@{ 
    ViewBag.Title = "Home Page"; 
    @Html.Partial("_Form"); 
} 

最后是我的局部视图_Form.cshtml的局部视图;我将只显示第一个下拉列表的文件的前半部分。 在顶部,包括我的模型MakeViewModel这是我们可以找到我们的车的名单,使..

@model VehicleMVC.Models.MakeViewModel 
<script src="@Url.Content("~/Scripts/jquery-1.10.2.min.js")" 
    type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" 
    type="text/javascript"></script> 

我用Ajax.BeginForm()调用GET方法使()从我VehicleController更新我的makes_DDL,因为我希望页面加载时填充列表。老实说问题可能在这里,因为我不确定它是正确的。

@using (Ajax.BeginForm("Makes", "Vehicle", new AjaxOptions 
    { 
     HttpMethod = "GET", 
     UpdateTargetId = "makes_DDL" 
    })) 

我用Html.DropDownListFor()创建makes_DDL列表,虽然它总是给我的错误“不设置到对象的实例对象引用”。

@Html.DropDownListFor(model => model.SelectedMakeId, 
    (SelectList)Model.MakesList, new { @class = "makes_DDL" }) 

非常感谢你提前!


有些事情我想: 我尝试使用新的SelectList,但没有运气:

@Html.DropDownListFor(model => model.SelectedMakeId, new 
    SelectList(Model.MakesList, "MakeId", "MakeName")) 

然后我试图硬编码品牌的测试列表,但相同的“对象未设置到一个对象的实例“错误。

@Html.DropDownListFor(model => model.SelectedMakeId, 
    new SelectList(new List<VehicleMVC.Models.Make> 
    { 
     new VehicleMVC.Models.Make { MakeId = 0, MakeName = "SmallCar"}, 
     new VehicleMVC.Models.Make { MakeId = 1, MakeName = "BigCar"} 
    }, 
    "value", "text", 0), new { @class = "makes_DDL" }) 

既然我敢肯定的是,Ajax.BeginForm没有做我想要的(从我VehicleController调用get使得()方法来填充makes_DDL列表)是什么,我试图用$(文件)。就绪()使用getJSON来使用应该调用Makes()的路由“api/vehicle”,但它似乎不会触发getJSON,因为我放入的警报不会触发。

<script type="text/javascript"> 
    function getMakes() { 
     $.getJSON("api/vehicle", 
      function (data) { 
       //This alert doesn't fire, so it seems getJSON is not firing?    
       window.alert(1); 
       //Code would later go here for appending the makes from the 
        returned IEnumerable to the makes_DDL list 
      }); 
    } 

$(document).ready(getMakes); 
</script> 
+0

你为什么不能填充你的第一个下拉列表中的内容在你的MVC操作方法,使您的看法?您正在获取空引用异常,因为“Model.MakesList”可能为空。或'Model'可能为空。您尚未分享GET操作的外观。 – Shyju

+0

建议你看看[这个DotNetFiddle](https://dotnetfiddle.net/1bPZym)中的代码 - 它的MVC,但应该给你的基本纲要 –

+0

拍摄,我认为你是对的。我只是意识到我似乎没有任何实际将制作放入我的MakesViewModel中的MakesList中的任何东西。我记得其他人使用Controller类而不是ApiController似乎做了类似“return View(obj)”的事情。 能否详细介绍一下我将如何将从我的VehicleController中的方法返回的汽车的IEnumerable存储到我的Model(我的MakeViewModel类中的MakesList)中?我很困惑,因为它似乎不应该使用像ActionResult Index()这样的东西。 谢谢你的回复! –

回答

0

而不是使用@Html.DropDownListFor可以使用<select>标签如下,

<select id="SelectedMakeId" name="SelectedMakeId"></select> 

然后你就可以用getJson

$(document).ready(function (e) { 
    $.getJSON("http://localhost:2390/api/vehicle", function (data) { 
     $.each(data, function (index, value) { 
      $("#SelectedMakeId").append("<option value=" + value.MakeId + ">" + value.MakeName + "</option>"); 
     }); 
    }); 
}); 

请注意,你必须给正确的API方法填充它网址。而不是给这个网址http://localhost:2390/api/vehicle你必须给你的路径。

你可以尝试这其中也

您可以使用ViewBag为好。对于做到以下几点,

1.设置路线API方法Makes()

 [System.Web.Http.Route("api/Vehicle/MakersList")] 
    [System.Web.Http.HttpGet] 
    public IEnumerable<Make> Makes() 
    { 
     ... 
    } 

2.更改Index方法

添加GetMakers()方法消耗API方法。使用此GetMakers()初始化ViewBag.listMakers

 private string MAKER_URL = "http://localhost:2390/api/vehicle"; 
    public ActionResult Index() 
    { 
      ViewBag.listMakers = new SelectList(GetMakers(), "MakeId","MakeName"); 
      return View(); 
    } 

    public IEnumerable<Make> GetMakers() 
    { 
     try 
      { 
       HttpClient client = new HttpClient(); 
       client.BaseAddress = new Uri(MAKER_URL); 
       client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
       HttpResponseMessage response = client.GetAsync("vehicle/MakersList").Result; 
       if (response.IsSuccessStatusCode) 
        return response.Content.ReadAsAsync<IEnumerable<Make>>().Result; 
       return null; 
      } 
      catch 
      { 
       return null; 
      } 

    } 

3.改写@Html.DropDownListFor

@Html.DropDownListFor(model => model.SelectedMakeId, (IEnumerable<SelectListItem>)ViewBag.listMakers, "---Select---", new { @class = "makes_DDL" }) 
+0

噢谢谢你的回复!我创建了第二个类似的列表,但没有想到只是完全删除Html.DropDownListFor并且还使用getJSON作为第一个列表。谢谢,我会试试看! –

+0

@YoshiKirishima查看最新的答案.. –

+0

再次感谢你!我将探索这两种选择。第一个对我来说效果不错!我的getJSON遇到问题,因为我认为我应该遵循RouteConfig中的路由URL,而不是WebApiConfig中的URL。一旦我使用地址API /车辆/而不是API /车辆,它的工作! –

相关问题