我正在使用WebRequest从FCC读取JSON数据,因此我可以将其输出到视图中。这是我持有FCC许可证的自定义类:
public class License
{
public string Name{ get; set; }
public string Frn { get; set; }
public string Callsign { get; set;}
public string CategoryDesc { get; set; }
public string ServiceDesc { get; set; }
public string StatusDesc { get; set; }
public DateTime ExpiredDate { get; set; }
public string Id { get; set; }
public string DetailUrl { get; set; }
}
这是我用来读取json结果的Controller动作 我现在将Verizon Wireless硬编码为搜索值:
public ActionResult GetLicenses()
{
var result = string.Empty;
var url = "http://data.fcc.gov/api/license-view/basicSearch/getLicenses?searchValue=Verizon+Wireless&format=jsonp&jsonCallback=?";
var webRequest = WebRequest.Create(url);
webRequest.Timeout = 2000;
using (var response = webRequest.GetResponse() as HttpWebResponse)
{
if (response.StatusCode == HttpStatusCode.OK)
{
var receiveStream = response.GetResponseStream();
if (receiveStream != null)
{
var stream = new StreamReader(receiveStream);
result = stream.ReadToEnd();
}
}
}
return new ContentResult { Content = result, ContentType = "application/json" };
}
这是观点。我试图枚举所有许可证并将它们输出到表格,但是当我转到/ Home / GetLicenses时,它会提示我下载文件:
@model IEnumerable<MvcApplication1.Models.License>
@{
ViewBag.Title = "Licenses";
}
<h2>Licenses</h2>
<table>
<tr>
<th>
Name
</th>
<th>
Frn
</th>
<th>
Callsign
</th>
<th>
CategoryDesc
</th>
<th>
ServiceDesc
</th>
<th>
StatusDesc
</th>
<th>
ExpiredDate
</th>
<th>
DetailUrl
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Frn)
</td>
<td>
@Html.DisplayFor(modelItem => item.Callsign)
</td>
<td>
@Html.DisplayFor(modelItem => item.CategoryDesc)
</td>
<td>
@Html.DisplayFor(modelItem => item.ServiceDesc)
</td>
<td>
@Html.DisplayFor(modelItem => item.StatusDesc)
</td>
<td>
@Html.DisplayFor(modelItem => item.ExpiredDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.DetailUrl)
</td>
</tr>
}
</table>
如果我通过jquery的getJSON方法直接进行上述操作,我得到了上述工作,但我想看看是否可以将控制器中的结果传递给视图,然后在视图中进行渲染。
这是结果变量中返回的内容的示例:
?({
"status": "OK",
"Licenses": {
"page": "1",
"rowPerPage": "100",
"totalRows": "1995",
"lastUpdate": "Sep 21, 2011",
"License": [
{
"licName": "CELLCO PARTNERSHIP (\"VERIZON WIRELESS\")",
"frn": "",
"callsign": "",
"categoryDesc": "Satellite Earth Station",
"serviceDesc": "",
"statusDesc": "Active",
"expiredDate": "",
"licenseID": "2300007967",
"licDetailURL": "http://licensing.fcc.gov/cgi-bin/ws.exe/prod/ib/forms/reports/swr031b.hts?prepare=&column=V_SITE_ANTENNA_FREQ.file_numberC/File+Number&q_set=V_SITE_ANTENNA_FREQ.file_numberC/File+Number/=/FCNNEW2000060800036"
},
{
"licName": "CELLO PARTNERSHIP (\"VERIZON WIRELESS\")",
"frn": "",
"callsign": "",
"categoryDesc": "Satellite Earth Station",
"serviceDesc": "",
"statusDesc": "Active",
"expiredDate": "",
"licenseID": "2300010661",
"licDetailURL": "http://licensing.fcc.gov/cgi-bin/ws.exe/prod/ib/forms/reports/swr031b.hts?prepare=&column=V_SITE_ANTENNA_FREQ.file_numberC/File+Number&q_set=V_SITE_ANTENNA_FREQ.file_numberC/File+Number/=/FCNNEW2000083100048"
},
{
"licName": "Cellco Partnership d/b/a Verizon Wireless",
"frn": "0003290673",
"callsign": "KE2XMC",
"categoryDesc": "Experimental",
"serviceDesc": "Experimental Developmental",
"statusDesc": "Unknown",
"expiredDate": "12/14/2000",
"licenseID": "3000020853",
"licDetailURL": "https://fjallfoss.fcc.gov/oetcf/els/reports/ELSSearchResult.cfm?callsign=KE2XMC"
},
{
"licName": "Cellco Partnership d/b/a Verizon Wireless",
"frn": "0003290673",
"callsign": "WA2XPS",
"categoryDesc": "Experimental",
"serviceDesc": "Experimental Developmental",
"statusDesc": "Unknown",
"expiredDate": "12/14/2000",
"licenseID": "3000020851",
"licDetailURL": "https://fjallfoss.fcc.gov/oetcf/els/reports/ELSSearchResult.cfm?callsign=WA2XPS"
},
{
"licName": "Cellco Partnership dba Verizon Wireless",
"frn": "0003290673",
"callsign": "KNKP866",
"categoryDesc": "Mobile/Fixed Broadband",
"serviceDesc": "Cellular",
"statusDesc": "Cancelled",
"expiredDate": "10/01/2005",
"licenseID": "13328",
"licDetailURL": "http://wireless2.fcc.gov/UlsApp/UlsSearch/license.jsp?__newWindow=false&licKey=13328"
}
]
}
})
我添加了这个课程:
public class FCC
{
public string status { get; set; }
public Licenses Licenses { get; set; }
}
但我仍然得到无效的JSON原语。
public ActionResult GetLicenses()
{
var result = string.Empty;
var url =
"http://data.fcc.gov/api/license-view/basicSearch/getLicenses?searchValue=Verizon+Wireless&format=jsonp&jsonCallback=?";
var webRequest = WebRequest.Create(url);
webRequest.Timeout = 2000;
webRequest.ContentType = "application/json";
using (var response = webRequest.GetResponse() as HttpWebResponse)
{
if (response.StatusCode == HttpStatusCode.OK)
{
var receiveStream = response.GetResponseStream();
if (receiveStream != null)
{
var stream = new StreamReader(receiveStream);
result = stream.ReadToEnd();
}
}
}
FCC fcc = new FCC();
if (result.StartsWith(@"?("))
{
result = result.Substring(2);
}
if (result.EndsWith(@")"))
{
result = result.Remove(result.Length - 1);
}
if (result != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
fcc = serializer.Deserialize<FCC>(result);
}
return View(fcc.Licenses.License);
}
答案 0 :(得分:1)
通过从ActionMethod返回ContentResult
,您的浏览器将根据内容以适当的操作进行响应。在这种情况下,将下载类似于文件的JSON字符串,因为它不是HTML文档。
如果要在View中呈现结果而不是通过AJAX,则需要创建一个表示WebRequest响应数据的C#Model类,然后返回ViewResult
并传递模型(或集合)模型)到视图。
我建议您更改ActionMethod
以执行以下操作,并创建名为“许可证”的视图
此外,您的示例响应有点棘手。它比原始许可证对象的数组更复杂,并且包含?()
。 JavaScriptSerializer将仅根据属性名称反序列化它可以匹配的属性(它也区分大小写)。由于?()
包装,我们需要将其删除,以便反序列化不会中断。
因此您需要相应地修改您的许可证对象:
public class FCC
{
public string status {get;set;}
public Licenses Licenses {get; set;}
}
public class License
{
public string licName{ get; set; }
public string frn { get; set; }
public string callsign { get; set;}
public string categoryDesc { get; set; }
public string serviceDesc { get; set; }
public string statusDesc { get; set; }
public string expiredDate { get; set; } //JSON dates and C# Dates are very finicky
public string licenseID { get; set; }
public string licDetailURL { get; set; }
}
public class Licenses
{
public int page {get; set;}
public int rowPerPage {get; set;}
public int totalRows {get; set;}
public string lastUpdate {get; set;}
public List<License> License {get; set;}
}
public ActionResult Licenses()
{
var result = string.Empty;
var url = "http://data.fcc.gov/api/license-view/basicSearch/getLicenses?searchValue=Verizon+Wireless&format=jsonp&jsonCallback=?";
var webRequest = WebRequest.Create(url);
webRequest.Timeout = 2000;
using (var response = webRequest.GetResponse() as HttpWebResponse)
{
if (response.StatusCode == HttpStatusCode.OK)
{
var receiveStream = response.GetResponseStream();
if (receiveStream != null)
{
var stream = new StreamReader(receiveStream);
result = stream.ReadToEnd();
}
}
}
FCC fcc = new FCC();
if (result.StartsWith(@"?("))
{
result = result.Substring(2);
}
if (result.EndsWith(@")"))
{
result = result.Remove(result.Length - 1);
}
if(result != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
fcc = serializer.Deserialize<FCC>(result);
}
return View(fcc.Licenses.License); //pass the data that your view needs
}
最后,您需要更改CSHTML文件中的属性名称,因为新的License对象不再具有相同的属性名称。
AJAX可能是另一个问题,但如果我遇到一个很好的例子,我会在这里回复
答案 1 :(得分:1)
我会尝试解决您的代码中的一些问题:
让我们从我们的视图模型开始:
public class License
{
public string Name { get; set; }
public string Frn { get; set; }
public string Callsign { get; set; }
public string CategoryDesc { get; set; }
public string ServiceDesc { get; set; }
public string StatusDesc { get; set; }
public DateTime ExpiredDate { get; set; }
public string Id { get; set; }
public string DetailUrl { get; set; }
}
public class Licenses
{
public License[] License { get; set; }
}
public class FCC
{
public string status { get; set; }
public Licenses Licenses { get; set; }
}
然后我们将拥有以下控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
using (var client = new WebClient())
{
var json = client.DownloadString("http://data.fcc.gov/api/license-view/basicSearch/getLicenses?searchValue=Verizon+Wireless&format=json");
var serializer = new JavaScriptSerializer();
var model = serializer.Deserialize<FCC>(json);
return View(model.Licenses.License);
}
}
}
请注意,在url中我不再指定要与JSONP一起使用的jsonCallback
查询字符串参数,我不想要JSONP,我想要JSON。就此而言,我还设置了format=json
参数。
最后我们可以看到以下~/Views/Home/Index.cshtml
视图:
@model IEnumerable<License>
<table>
<thead>
<tr>
<th>
Name
</th>
<th>
Frn
</th>
<th>
Callsign
</th>
<th>
CategoryDesc
</th>
<th>
ServiceDesc
</th>
<th>
StatusDesc
</th>
<th>
ExpiredDate
</th>
<th>
DetailUrl
</th>
<th></th>
</tr>
</thead>
<tbody>
@Html.DisplayForModel()
</tbody>
</table>
以及将为Licenses集合(~/Views/Home/DisplayTemplates/License.cshtml
)的每个元素呈现的相应显示模板:
@model License
<tr>
<td>
@Html.DisplayFor(x => x.Name)
</td>
<td>
@Html.DisplayFor(x => x.Frn)
</td>
<td>
@Html.DisplayFor(x => x.Callsign)
</td>
<td>
@Html.DisplayFor(x => x.CategoryDesc)
</td>
<td>
@Html.DisplayFor(x => x.ServiceDesc)
</td>
<td>
@Html.DisplayFor(x => x.StatusDesc)
</td>
<td>
@Html.DisplayFor(x => x.ExpiredDate)
</td>
<td>
@Html.DisplayFor(x => x.DetailUrl)
</td>
</tr>
好的,到目前为止,我们的地址是第1点和第2点。
现在是第三个。此同步调用的问题是以下行:client.DownloadString
。这是一个阻止电话。阻止对远程资源的调用在ASP.NET应用程序中非常糟糕。在这里你获取一些可能需要时间的远程资源=&gt;你将遍历网络边界,互联网防火墙,......直到你点击远程网络服务器本身,为了服务请求将查询数据库,...你明白了:它很慢。在这段时间里,您的Web应用程序正在等待并且线程被垄断。请记住,您可以使用有限数量的工作线程,因此不要浪费它们。
解决此问题very serious issue的方法是使用asynchronous controllers和I / O完成端口。这些内容直接构建在Windows内核中,允许您执行IO密集型操作,而不会阻塞和独占服务器上的线程。
以下是您的HomeController将如何变为:
public class HomeController : AsyncController
{
public void IndexAsync()
{
var client = new WebClient();
AsyncManager.OutstandingOperations.Increment();
client.DownloadStringCompleted += (s, e) =>
{
AsyncManager.OutstandingOperations.Decrement();
if (e.Error != null)
{
AsyncManager.Parameters["error"] = e.Error.Message;
}
else
{
var serializer = new JavaScriptSerializer();
var model = serializer.Deserialize<FCC>(e.Result);
AsyncManager.Parameters["licenses"] = model.Licenses.License;
}
};
client.DownloadStringAsync(new Uri("http://data.fcc.gov/api/license-view/basicSearch/getLicenses?searchValue=Verizon+Wireless&format=json"));
}
public ActionResult IndexCompleted(License[] licenses, string error)
{
if (!string.IsNullOrEmpty(error))
{
ModelState.AddModelError("licenses", error);
}
return View(licenses ?? Enumerable.Empty<License>());
}
}
答案 2 :(得分:0)
这是我做的,它在DIV中向我展示了Json数据......
public JsonResult GetLicenses()
{
var result = string.Empty;
const string url = "http://data.fcc.gov/api/license-view/basicSearch/getLicenses?searchValue=Verizon+Wireless&format=jsonp&jsonCallback=?";
var webRequest = WebRequest.Create(url);
webRequest.Timeout = 2000;
using (var response = webRequest.GetResponse() as HttpWebResponse)
{
if (response != null && response.StatusCode == HttpStatusCode.OK)
{
var receiveStream = response.GetResponseStream();
if (receiveStream != null)
{
var stream = new StreamReader(receiveStream);
result = stream.ReadToEnd();
}
}
}
return Json(result,JsonRequestBehavior.AllowGet);
返回类型Json并在Action
中键入JsonResult如果你想通过AJAX调用它,那么这里是
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: 'GET',
url: '@Url.Action("GetLicenses","Home")',
success: function (data) {
$('#content').html(data);
},
error: function (data) {
$('#content').append(data);
}
});
});
并确保在_Layout.cshtml中引用Jquery文件..