ASP.NET Web API中的JSON和XML序列化

前言

阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html

本文描述ASP.NET Web API中的JSON和XML格式化器。

在ASP.NET Web API中,媒体类型格式化器(Media-type Formatter)是一种能够做以下工作的对象:

  • 从HTTP消息体读取CLR(公共语言运行时)对象
  • 将CLR对象写入HTTP消息体

Web API提供了用于JSON和XML的媒体类型格式化器。框架已默认将这些格式化器插入到消息处理管线之中。客户端在HTTP请求的Accept报头中可以请求JSON或XML。

JSON媒体类型格式化器

JSON格式化是由JsonMediaTypeFormatter类提供的。默认情况下,JsonMediaTypeFormatter使用Json.NET库执行序列化工作。Json.NET是一个第三方开源项目。

如果喜欢,你可以将JsonMediaTypeFormatter配置成使用DataContractJsonSerializer来代替Json.NET。要想这么做,只需UseDataContractJsonSerializer将属性设置为true即可:

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.UseDataContractJsonSerializer = true;

JSON序列化

本小节描述,在使用默认的Json.NET序列化器时,JSON格式化器的一些特定行为。这并不意味着要包含Json.NET库的整个文档。更多信息参阅Json.NET Documentation。

什么会被序列化?

默认情况下,所有public属性和字段都会被包含在序列化的JSON中。为了忽略一个属性或字段,需要用JsonIgnore注解属性修饰它。

public class Product
{
public string Name { get; set; }
public decimal Price { get; set; } [JsonIgnore]
public int ProductCode { get; set; } // omitted
}

如果你更喜欢“opt-in(选入)”方法,可以用DataContract注解属性来修饰类。如果有注解属性,则成员均被忽略,除非有DataMemberDataMember也可以序列化private成员。

[DataContract]
public class Product
{
[DataMember]
public string Name { get; set; } [DataMember]
public decimal Price { get; set; }
public int ProductCode { get; set; } // omitted by default
}

只读属性

只读属性默认是序列化的。

Dates(日期)

默认情况下,Json.NET会将日期写成ISO 8601格式。UTC(Coordinated Universal Time — 世界标准时间)格式的日期书写时带有后缀“Z”。本地时间格式的日期包括了一个时区偏移量。例如:

2012-07-27T18:51:45.53403Z         // UTC(标准时间)
2012-07-27T11:51:45.53403-07:00 // Local(本地时间)

默认情况下,Json.NET保留时区。通过设置DateTimeZoneHandling属性,可以重写这一行为:

// Convert all dates to UTC
// 将所有日期转换成UTC格式
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.DateTimeZoneHandling =
Newtonsoft.Json.DateTimeZoneHandling.Utc;

如果你喜欢使用微软的JSON日期格式("\/Date(ticks)\/ ")而不是ISO 8601,可以在SerializerSettings上设置DateFormatHandling属性:

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.DateFormatHandling =
Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;

Indenting(缩进)

为了书写有缩进的JSON,可以将Formatting设置为Formatting.Indented

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.Formatting =
Newtonsoft.Json.Formatting.Indented;

Camel Casing(驼峰式大小写转换)

为了在不修改数据模型的情况下,用驼峰式大小写转换JSON的属性名,可以设置序列化器上的CamelCasePropertyNamesContractResolver

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver();

匿名类型与弱类型对象

动作方法或以返回一个匿名对象,并将其序列化成JSON。例如:

public object Get()
{
return new {
Name = "Alice",
Age = 23,
Pets = new List<string> { "Fido", "Polly", "Spot" }
};
}

响应消息体将含有以下JSON:

{"Name":"Alice","Age":23,"Pets":["Fido","Polly","Spot"]}

如果Web API从客户端接收了松散结构的JSON,你可以将该请求体解序列化成Newtonsoft.Json.Linq.JObject类型。

public void Post(JObject person)
{
string name = person["Name"].ToString();
int age = person["Age"].ToObject<int>();
}

然而,通常更好的是使用强类型数据对象。那么,便不需要自行对数据进行解析,并且能得到模型验证的好处。

XML序列化器不支持匿名类型或JObject实例。如果将这些特性用于JSON数据,应该去掉管线中的XML格式化器,如本文稍后描述的那样。

XML媒体类型格式化器

  XML格式化是由XmlMediaTypeFormatter类提供的。默认情况下,XmlMediaTypeFormatter使用DataContractSerializer类来执行序列化。如果喜欢,你可以将XmlMediaTypeFormatter配置成使用XmlSerializer而不是DataContractSerializer。要想这么做,可将UseXmlSerializer属性设置为true: 

var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;

XmlSerializer类支持的类型集要比DataContractSerializer更窄一些,但对结果XML有更多的控制。如果需要与已有的XML方案匹配,可考虑使用XmlSerializer

XML Serialization——XML序列化

本小节描述使用默认DataContractSerializer的时,XML格式化器的一些特殊行为。默认情况下,DataContractSerializer行为如下:

  •   序列化所有public读/写属性和字段。为了忽略一个属性或字段,请用IgnoreDataMember注解属性修饰它。
  •   private和protected成员不作序列。
  •   只读属性不作序列化
  •   类名和成员名按类声明中的确切呈现写入XML
  •   使用XML的默认命名空间

如果需要在序列化上的更多控制,可以用DataContract注解属性修饰类。当这个注解属性出现时,该类按以策略序列化:

  •   “Opt in(选入)”方法:属性与字段默认不被序列化。为了序列化一个属性或字段,请用DataMember注解属性修饰它。
  •   要序列化private或protected成员,请用DataMember注解属性修饰它。
  •   只读属性不被序列化。
  •   要改变类名在XML中的呈现,请在DataContract注解属性中设置Name参数。
  •   要改变成员名在XML中的呈现,请设置DataMember注解属性中的Nmae参数。
  •   要改变XML命名空间,请设置DataContract类中的Namespace参数。

Read-Only Properties——只读属性

只读属性是不被序列化的。如果只读属性有一个支撑private字段,可以用DataMember注解属性对这个private字段进行标记。这种办法需要在类上使用DataContract注解属性。

[DataContract]
public class Product
{
[DataMember]
private int pcode; // serialized(序列化的) // Not serialized (read-only)
// 不作序列化(只读)
public int ProductCode { get { return pcode; } }
}

Dates——日期

日期被写成ISO 8601格式。例如,“2012-05-23T20:21:37.9116538Z”。

Indenting——缩进

要书写缩进的XML,请将Indent属性设置为true

var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.Indent = true;

设置每一类型(Per-Type)的XML序列化器

你可以为不同的CLR类型设置不同的XML序列化器。例如,你可能有一个特殊的数据对象,它出于向后兼容而需要XmlSerializer。你可以为此对象使用XmlSerializer,而对其它类型继续使用DataContractSerializer

为了设置用于特殊类型的XML序列化器,要调用SetSerializer

var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
// Use XmlSerializer for instances of type "Product":
// 对“Product”类型的实例使用XmlSerializer:
xml.SetSerializer<Product>(new XmlSerializer(typeof(Product)));

你可以指定一个XmlSerializer,或任何派生于XmlObjectSerializer的对象。

Removing the JSON or XML Formatter——去除JSON或XML格式化器

你可以从格式化器列表中删除JSON格式化器,或XML格式化器,只要你不想使用它们。这么做的主要原因是:

  •   将你的Web API响应限制到特定的媒体类型。例如,你可能决定只支持JSON响应,而删除XML格式化器。
  •   用一个自定义格式化器代替默认的格式化器。例如,你可能要用自己的自定义JSON格式化器实现来代替(默认的)JSON格式化器。

以下代码演示了如何删除默认的格式化器。在Global.asax中定义的Application_Start方法中调用它。

void ConfigureApi(HttpConfiguration config)
{
// Remove the JSON formatter
// 删除JSON格式化器
config.Formatters.Remove(config.Formatters.JsonFormatter); // or(或者) // Remove the XML formatter
// 删除XML格式化器
config.Formatters.Remove(config.Formatters.XmlFormatter);
}

Handling Circular Object References——处理循环对象引用

在默认情况下,JSON和XML格式化器将所有对象都写成值。如果两个属性引用了同一个对象,或者,如果在一个集合同一个对象出现了两次,格式化器将对此对象做两次序列化。这是在对象图含有循环的情况下会出现的特有问题,因为,序列化器在检测到对象图中的循环时,会抛出异常。

考虑以下对象模型和控制器。

public class Employee
{
public string Name { get; set; }
public Department Department { get; set; }
} public class Department
{
public string Name { get; set; }
public Employee Manager { get; set; }
} public class DepartmentsController : ApiController
{
public Department Get(int id)
{
Department sales = new Department() { Name = "Sales" };
Employee alice = new Employee() { Name = "Alice", Department = sales };
sales.Manager = alice;
return sales;
}
}

调用此动作会触发格式化器抛出异常,该异常将转换成发送给客户端的状态代码500(内部服务器错误)响应。

为了保留JSON中的对象引用,对Global.asax文件的Application_Start方法添加以下代码:

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.All;

现在,此控制器动作将返回类似于如下形式的JSON:

{"$id":"1","Name":"Sales","Manager":{"$id":"2","Name":"Alice","Department":{"$ref":"1"}}}

注意,序列化器对两个对象都添加了一个“$id”。而且,它检测到Employee.Department属性产生了一个循环,因此,它用一个对象引用{"$ref":"1"}代替这个值。

对象引用是不标准的JSON。在使用此特性之前,要考虑你的客户端是否能够解析这种结果。简单地去除对象图中的循环,可能是更好的办法。例如,此例中Employee链接回Department并不是真正的需要。

为了保留XML中的对象引用,可以使用两个选项。较简单的选项是对模型类添加[DataContract(IsReference=true)]。IsReference参数启用了对象引用。记住,DataContract构成了序列化的“选入(Opt-in)”,因此,你还需要对属性添加DataMember注解属性:

[DataContract(IsReference=true)]
public class Department
{
[DataMember]
public string Name { get; set; } [DataMember]
public Employee Manager { get; set; }
}

现在,该格式化器将产生类似于如下形式的XML:

<Department xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1"
xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"
xmlns="http://schemas.datacontract.org/2004/07/Models">
<Manager>
<Department z:Ref="i1" />
<Name>Alice</Name>
</Manager>
<Name>Sales</Name>
</Department>

如果想避免在模型类上使用注解属性,还有另一个选项:创建新的类型专用的DataContractSerializer实例,并在构造器中将preserveObjectReferences设置为true

var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
var dcs = new DataContractSerializer(typeof(Department), null, int.MaxValue,
false, /* preserveObjectReferences: */ true, null);
xml.SetSerializer<Department>(dcs);

Testing Object Serialization——测试对象序列化

在设计Web API时,对如何序列化对象进行测试是有用的。不必创建控制器或调用控制器动作,便可做这种事。

string Serialize<T>(MediaTypeFormatter formatter, T value)
{
// Create a dummy HTTP Content.
// 创建一个HTTP内容的哑元
Stream stream = new MemoryStream();
var content = new StreamContent(stream); // Serialize the object.
// 序列化对象
formatter.WriteToStreamAsync(typeof(T), value, stream, content.Headers, null).Wait(); // Read the serialized string.
// 读取序列化的字符串
stream.Position = 0;
return content.ReadAsStringAsync().Result;
} T Deserialize<T>(MediaTypeFormatter formatter, string str) where T : class
{
// Write the serialized string to a memory stream.
// 将序列化的字符器写入内在流
Stream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(str);
writer.Flush();
stream.Position = 0; // Deserialize to an object of type T
// 解序列化成类型为T的对象
return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T;
} // Example of use
// 使用示例(用例)
void TestSerialization()
{
var value = new Person() { Name = "Alice", Age = 23 }; var xml = new XmlMediaTypeFormatter();
string str = Serialize(xml, value); var json = new JsonMediaTypeFormatter();
str = Serialize(json, value); // Round trip
// 反向操作(解序列化)
Person person2 = Deserialize<Person>(json, str);
}

总结

本课主要简单的了解一下JSON和XML的序列化和反序列的使用。

本文的参考链接为 http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization

同时本文已更新至 Web API导航系列 http://www.cnblogs.com/aehyok/p/3446289.html

 

跨浏览器开发工作小结

 

  本篇小结是在2011年时候总结的,当时做一个产品的跨浏览器兼容工作,由于产品开发的时间比较早,最开始只能在IE下面(IE 8、IE 9还有点点问题)使用,做跨浏览器兼容工作的时候,主要是适配IE 6--IE 9、Safari、FireFox、Chrome,引入了jQuery框架进行改造后,大部分功能可以正常使用,现将总结分享一下。

1.eval(idName)

  【问题描述】:IE、safari、Chrome浏览器下都可以使用eval(idName)或getElementById(idName)来取得id为idName的HTML对象;firefox下只能使用getElementById(idName)来取得id为idName的HTML对象.

  【兼容办法】:统一用getElementById("idName")来取得id为idName的HTML对象。

2.ActiveXObject

  【问题描述】:IE下支持用var obj = new ActiveXObject() 的方式创建对象,但其它浏览器都会提示ActiveXObject对象未定义。

  【兼容办法】:

  (1)在使用new ActiveXObject()之前先判断浏览器是否支持ActiveXObject对象,以创建AJAX对象为例:

1 if(window.ActiveXObject)
2 {
3 this.req=new ActiveXObject("Microsoft.XMLHTTP");
4 }
5 else if(window.XMLHttpRequest)
6 {
7 this.req=new XMLHttpRequest();
8 }

  (2)使用jQuery封装的ajax方法来创建对象,以创建AJAX对象为例(推荐)

 1 var strResponse = "";
2 jQuery.ajax({ url: sAspFile, data: "<root>" + sSend + "</root>", processData: false, async: false, type: "POST",
3 error: function(XMLHttpRequest, textStatus, errorThrown)
4 {
5 strResponse = textStatus;
6 },
7 success: function(data, textStatus)
8 {
9 strResponse = data;
10 }
11 });

3.XML操作

  【问题描述】:通常装载xml文档使用ActiveXObject对象,但除非IE外,其它浏览器都不支持此方法。XML文档操作,IE和其它浏览器也存在不同,通常取XML对象的XML文本的方法是xml.documentElement.xml,但xml属性只有IE支持,其它浏览器均不支持。查找节点是常用的方法有selectNodes和selectSingleNode,这两个方法也只有IE支持,其它浏览器需要自己扩展。

  【兼容办法】

  (1)装载XML文档:用$.ajax(),参考jquery帮助文档

  (2)xml对象转字符串,如:

 1 var stringtoxml = function(str) { //字符串转xml对象
2 var s = "<?xml version='1.0' encoding='utf-8' ?>" + str;
3 var objxml = null;
4 if (window.ActiveXObject) {
5 objxml = new ActiveXObject("Microsoft.XMLDOM");
6 objxml.async = false;
7 objxml.loadXML(s);
8 }
9 else {
10 objxml = (new DOMParser()).parseFromString(s, "text/xml");
11 }
12 return objxml;
13 }
14
15 var xmltostring = function(dom) { //xml对象转字符串
16 if (dom instanceof jQuery) {
17 dom = dom[0];
18 }
19 var str = null;
20 if (window.ActiveXObject) {
21 str = dom.xml;
22 }
23 else {
24 str = (new XMLSerializer()).serializeToString(dom);
25 }
26 return str;
27 }
28
29 var oXMLO = stringtoxml("<root>"+ xml +"</root>");
30 var root = oXMLO.documentElement;
31 var strXml = xmltostring(root).replace("<root>","");

  (3)字符串转xml对象,如:

1 var oXML = stringtoxml("<root>" + document.getElementById("hidTaskXml").value + "</root>");

  (4)查找结点:可以用JQUERY同的find方法来查找结点,如:

1 var item = $(oXML).find("record");

  或者用原型扩展方法为XML对象添加selectNodes和selectSingleNode方法,扩展方法如下:

if( document.implementation.hasFeature("XPath", "3.0") )
{
XMLDocument.prototype.selectNodes =function(cXPathString, xNode)
{
if( !xNode )
{
xNode = this;
}
var oNSResolver = this.createNSResolver(this.documentElement); var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null) ; var aResult = []; for( var i = 0; i < aItems.snapshotLength; i++)
{
aResult[i] = aItems.snapshotItem(i);
} return aResult;
} Element.prototype.selectNodes = function(cXPathString)
{
if(this.ownerDocument.selectNodes)
{
return this.ownerDocument.selectNodes(cXPathString, this);
}
else
{
throw "For XML Elements Only";
}
} XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode)
{
if( !xNode )
{
xNode = this;
}
var xItems = this.selectNodes(cXPathString, xNode);
if( xItems.length > 0 )
{
return xItems[0];
}
else
{
return null;
}
} Element.prototype.selectSingleNode = function(cXPathString)
{
if(this.ownerDocument.selectSingleNode)
{
return this.ownerDocument.selectSingleNode(cXPathString, this);
}
else
{
throw "For XML Elements Only";
}
}
}

4.window.execScript()

  【问题描述】:只有IE浏览器支持execScript方法,其它的都不支持。但所有浏览器都支持window.eval()方法。

  【兼容办法】:用window.eval()方法代替window.execScript()。如

1 //window.execScript(“alert(123)”);
2
3 window.eval(“alert(123)”);

5.window.createPopup()

  【问题描述】:创建一个弹出窗口的方法,IE支持此方法,Safari、FireFox、Chrome都不支持,使用时会提示createPopup方法未定义。

  【兼容办法】:可用如下方法为window对象添加createPopup方法。

if (!window.createPopup) {
var __createPopup = function() {
var SetElementStyles = function( element, styleDict ) {
var style = element.style ;
for ( var styleName in styleDict )style[ styleName ] = styleDict[ styleName ] ;
}
var eDiv = document.createElement( 'div' );
SetElementStyles( eDiv, { 'position': 'absolute', 'top': 0 + 'px', 'left': 0 + 'px', 'width': 0 + 'px', 'height': 0 + 'px', 'zIndex': 1000, 'display' : 'none', 'overflow' : 'hidden' } ) ;
eDiv.body = eDiv ;
var opened = false ;
var setOpened = function( b ) {
opened = b;
} var getOpened = function() {
return opened ;
} var getCoordinates = function( oElement ) {
var coordinates = {x:0,y:0} ;
while( oElement ) {
coordinates.x += oElement.offsetLeft ;
coordinates.y += oElement.offsetTop ;
oElement = oElement.offsetParent ;
}
return coordinates ;
}
return {
htmlTxt : '',
document : eDiv,
isOpen : getOpened(),
isShow : false,
hide : function() {
SetElementStyles( eDiv, { 'top': 0 + 'px', 'left': 0 + 'px', 'width': 0 + 'px', 'height': 0 + 'px', 'display' : 'none' } ) ;
eDiv.innerHTML = '' ;
this.isShow = false ;
},
show : function( iX, iY, iWidth, iHeight, oElement ) {
if (!getOpened()) {
document.body.appendChild( eDiv ) ; setOpened( true ) ;
} ;
this.htmlTxt = eDiv.innerHTML ;
if (this.isShow) {
this.hide() ;
} ;
eDiv.innerHTML = this.htmlTxt ;
var coordinates = getCoordinates ( oElement ) ;
eDiv.style.top = ( iX + coordinates.x ) + 'px' ;
eDiv.style.left = ( iY + coordinates.y ) + 'px' ;
eDiv.style.width = iWidth + 'px' ;
eDiv.style.height = iHeight + 'px' ;
eDiv.style.display = 'block' ;
this.isShow = true ;
}
}
}
window.createPopup = function() {
return __createPopup();
}
}

6.getYear()方法

  【问题描述】:如下代码:

1 var year= new Date().getYear();
2
3 document.write(year);

  在IE中得到的日期是"2011",在Firefox中看到的日期是"111",主要是因为在 Firefox 里面getYear返回的是 "当前年份-1900" 的值。

  【兼容办法】:解决办法是加上对年份的判断,如:

1 var year= new Date().getYear();
2 year = (year<1900?(1900+year):year);
3 document.write(year);

  也可以通过 getFullYear getUTCFullYear去调用:

1 var year = new Date().getFullYear();
2
3 document.write(year); 

7.document.all

  【问题描述】:document.all在IE、Safari下都可以使用,firefox、Chrome下不能使用

  【兼容办法】:所有以document.all.*方法获取对象的地方都改为document.getElementById或document.getElementsByName或document.getElementsByTagName。

8.变量名与对象ID相同的问题

  【问题描述】:IE下,HTML对象的ID可以作为document的下属对象变量名直接使用,如下面的写法:

objid.value = “123”;//objid为控件ID

  其它浏览器下则不能这样写。原因是其它浏览器下,可以使用与HTML对象ID相同的变量名,IE下则不能。

  【兼容办法】:使用document.getElementById(idName)等通用方法先获取对象,再操行其它操作。如:

document.getElementById(objid).value = “123”; //objid为控件ID

  注:最好不要取HTML对象ID相同的变量名,以减少错误;在声明变量时,一律加上var,以避免歧义。

9.select元素的add方法

  【问题描述】:在IE,Safari,Chrome下,select控件添加项时使用如下的方法:

document.getElementById(“select1”).add(new Options(“aa”,”aa”));

  但在FireFox下这样操作会报错。

  【兼容办法】:统一使用兼容方法,加options属性,如下:

document.getElementById(“select1”).options.add(new Options(“aa”,”aa”));

10.html元素的自定义属性

  【问题描述】:IE下元素属性访问方法如document.getElementById(id).属性名,而且对于自定义属性和非自定义属性均有效。但在其它浏览器下该方法只适应于元素的公共属性,自定义属性则取不到。

  【兼容办法】:用jQuery的方法来取,如$(“#id”).attr(“属性”)或用document.getElementById(id).getAttribute(“属性”),两种方法都可以适用所有浏览器。

11.html元素innerText属性

  【问题描述】:取元素文本的属性innerText在IE中能正常工作,但此属性不是DHTML标准,其它浏览器不支持,其它浏览器中使用textContent属性获取。

  【兼容办法】:

  (1)通用方法是用jQuery方法$(“#id”).text(),如:

//document.getElementById(id).innerText;

$(“#id”).text();

  (2)取值前判断浏览器,根据具体情况取值,如:

var obj = document.getElementById(id);

var str = (obj.innerText)?obj.innerText:obj.textContent;

  (3)也可以通过原型扩展方法来为元素添加innerText,扩展方法如下:

if(typeof(HTMLElement)!="undefined" && !window.opera)
{
var pro = window.HTMLElement.prototype; pro.__defineGetter__("innerText",function (){
var anyString = "";
var childS = this.childNodes;
for(var i=0; i<childS.length; i++)
{
if(childS[i].nodeType==1)
{
anyString += childS[i].tagName=="BR" ? '\n' : childS[i].innerText;
}
else if(childS[i].nodeType==3)
{
anyString += childS[i].nodeValue;
}
}
return anyString;
}); pro.__defineSetter__("innerText",function(sText){
this.textContent=sText;
});
}

12.html元素innerHTML、outerHTML属性

  【问题描述】:innerHTML是所有浏览器都支持的属性。outerHTML属性不是DHTML标准,IE外的其它浏览器不支持。

  【兼容办法】:在非IE浏览器下必须使用扩展方法才能获取,扩展方法如下:

if(typeof(HTMLElement)!="undefined" && !window.opera)
{
var pro = window.HTMLElement.prototype;
pro.__defineGetter__("outerHTML", function(){
var str = "<" + this.tagName;
var a = this.attributes;
for(var i = 0, len = a.length; i < len; i++)
{
if(a[i].specified)
{
str += " " + a[i].name + '="' + a[i].value + '"';
}
}
if(!this.canHaveChildren)
{
return str + " />";
}
return str + ">" + this.innerHTML + "</" + this.tagName + ">";
}); pro.__defineSetter__("outerHTML", function(s){
var r = this.ownerDocument.createRange();
r.setStartBefore(this);
var df = r.createContextualFragment(s);
this.parentNode.replaceChild(df, this);
return s;
});
}

13.html元素parentElement属性

  【问题描述】:parentElement是取元素父结点的属性,此属性只有IE支持,其它浏览器均不支持。

  【兼容办法】:用parentNode属性来获取父结点,如:

//document.getElementById(id).parentElement;

document.getElementById(id).parentNode;

14.集合类对象问题

  【问题描述】:IE下对于集合类对象,如forms,frames等,可以使用()或[]获取集合类对象,Safari,Chrome也都支持,如

document.forms(“formid”) 或 document.forms[“formid”]。但Firefox下,只能使用[]获取集合类对象。

  【兼容办法】:统一使用[]获取集合类对象,如:

document.forms[0];

document.forms[“formid”];

  【注】:所有以数组方式存储的对象都在访问子成员时,都必须以[]方式索引得到,如常见的XML文档遍历,也需要改,如下:

// xmldoc.documentElement.childNodes(1) 

xmldoc.documentElement.childNodes[1]

15.frame操作

  【问题描述】:在IE、Safari、Chrome下,用window对象访问frame对象时,可以用id和name属性来获取,如

window.frameId;
window.frameName;

  但在firefox下,必须使用frame对象的name属性才能获取到。

  【兼容办法】:

  (1)访问frame对象:统一使用window.document.getElementById(frameId)来访问这个frame对象。

  (2)切换frame内容:统一使用window.document.getElementById(testFrame).src=xxx.htm切换。

  如果需要将frame中的参数传回父窗口,可以在frame中使用parent来访问父窗口。例如:parent.document.form1.filename.value=Aqing;

  (3)iframe页中的对象: $("#frameid").contents().find("#html控件id")

  (4)iframe页中的iframe: $("#frameid").contents().find("#frameid1").contents();

  (5)iframe中的方法或变量:$("#frameid")[0] .contentWindow.SaveFile("false", strRet, a);

16.insertAdjacentHTMLinsertAdjacentText

  【问题描述】:insertAdjacentHTML 方法是比 innerHTML、outerHTML 属性更灵活的插入 HTML 代码的方法。它可以实现在一个 DOM 元素的前面、后面、第一个子元素前面、最后一个子元素后面四个位置,插入指定的 HTML 代码。不是 W3C 标准的 DOM 方法,W3C 近期在 HTML5 草案中扩展了这个方法。

  insertAdjacentText 是比 innerText、outerText 属性更灵活的插入文本的方法。它可以实现在一个 DOM 元素的前面、后面、第一个子元素前面、最后一个子元素后面四个位置,插入指定的文本。不是 W3C 标准的 DOM 方法,至今为止 W3C 的 HTML5还未涉及此方法。

  insertAdjacentHTML和insertAdjacentText可以IE、Safari、Chrome上执行,只有FireFox不支持,

  【兼容办法】:可用以下方法进行扩展:

if (typeof(HTMLElement) != "undefined")
{
HTMLElement.prototype.insertAdjacentElement = function(where, parsedNode)
{
switch (where)
{
case "beforeBegin":
this.parentNode.insertBefore(parsedNode, this);
break;
case "afterBegin":
this.insertBefore(parsedNode, this.firstChild);
break;
case "beforeEnd":
this.appendChild(parsedNode);
break;
case "afterEnd":
if (this.nextSibling)
this.parentNode.insertBefore(parsedNode, this.nextSibling);
else
this.parentNode.appendChild(parsedNode);
break;
}
}
HTMLElement.prototype.insertAdjacentHTML = function(where, htmlStr)
{
var r = this.ownerDocument.createRange();
r.setStartBefore(this);
var parsedHTML = r.createContextualFragment(htmlStr);
this.insertAdjacentElement(where, parsedHTML);
} HTMLElement.prototype.insertAdjacentText = function(where, txtStr)
{
var parsedText = document.createTextNode(txtStr);
this.insertAdjacentElement(where, parsedText);
}
}  

17.Html元素的children属性

  【问题描述】:children是取HTML元素子结点的属性,只有IE下支持,其它浏览器下用childNodes。

  【兼容办法】:统一改为用childNodes属性取子结点。或用以下方法扩展HTML元素的属性:

if (typeof(HTMLElement) != "undefined")
{
HTMLElement.prototype.__defineGetter__("children",function(){
var returnValue = new Object();
var number = 0;
for(var i=0; i<this.childNodes.length; i++)
{
if(this.childNodes[i].nodeType == 1)
{
returnValue[number] = this.childNodes[i];
number++;
}
}
returnValue.length = number;
return returnValue;
})

18.insertRow\inserCell

  【问题描述】:insertRow和insertCell是在表格中插入行或插入列的方法,在IE中使用方法如下

var nowTB = document.getElementById("tb1");
nowTR = nowTB.insertRow();
nowTD = nowTR.insertCell();  

  Safari、Chrome下也可以正常执行,但插入行的位置不一样IE下默认在表尾插入行,Safari、Chrome默认在表头插入行;但在FireFox下调用会报错。

  【兼容办法】:下面的方法可以在所有浏览器上调用,而且插入行的位置都是表尾,不同之处就是执行前传递一个默认值。推荐使用。

var nowTB = document.getElementById("tb1");

nowTR = nowTB.insertRow(-1);

nowTD = nowTR.insertCell(-1);

19.document.createElement

  【问题描述】:IE有3种方式都可以创建一个元素:

1 document.createElement("<input type=text>")

2 document.createElement("<input>")

3 document.createElement("input")

  Safari、FireFox、Chrome只支持一种方式:

document.createElement("input");

document.setAttribute(name,value);

  【兼容办法】:统一使用所有浏览器都支持的方法,如下:

document.createElement("input");

document.setAttribute(name,value);

20.浏览器处理childNodes的异同

  【问题描述】:如下HTML代码:

<ul id="main">

<li>1</li>

<li>2</li>

<li>3</li>

</ul>

<input type=button value="click me!" onclick=

"alert(document.getElementById('main').childNodes.length)">

  分别用IE和其它浏览器运行,IE的结果是3,而其它则是7。

  IE是将一个完整标签作为一个节点,而Safari、FireFox、Chrome除了上述的的情况外,也把一个标签的结束符“>”到下一个标签的起始符“<”之间的内容(除注释外,包括任何的文字、空格、回车、制表符)也算是一个节点了,而且这种节点也有它们自己独特的属性和值nodeName="#text"。

  【兼容办法】:在实际运用中,Safari、FireFox、Chrome在遍历子节点时,在for循环里加上

  if(childNode.nodeName=="#text") continue;或者nodeType == 1 这样,便跳过不需要的操作,使程序运行的更有效率。也可以用node.getElementsByTagName()回避。

21.document.getElementsByName

  【问题描述】:在元素只有name属性,没有id属性的情况下,在IE中获取不到DIV元素,其它浏览器可以获取。当前name和id属性都存在时,所有浏览器都可以获取到DIV元素。

  【兼容办法】:尽量用ID来获取。

22.tr操作

  【问题描述】:IE下table中无论是用innerHTML还是appendChild插入<tr>都没有效果,因为在IE浏览器下tr是只读的。而其他浏览器下可以这样操作。

  【兼容办法】:将<tr>加到table的<tbody>元素中,如下面所示:

var row = document.createElement("tr");

var cell = document.createElement("td");

var cell_text = document.createTextNode("插入的内容");

cell.appendChild(cell_text);

row.appendChild(cell);

document.getElementsByTagName("tbody")[0].appendChild(row);

23.移除节点removeNode()

  【问题描述】:appendNode在IE和其它浏览器下都能正常使用,但是removeNode只能在IE下用。removeNode方法的功能是删除一个节点,语法为node.removeNode(false)或者node.removeNode(true),返回值是被删除的节点。

  removeNode(false)表示仅仅删除指定节点,然后这个节点的原孩子节点提升为原双亲节点的孩子节点。

  removeNode(true)表示删除指定节点及其所有下属节点。被删除的节点成为了孤立节点,不再具有有孩子节点和双亲节点。

  【兼容办法】:兼容IE和其它浏览器的方法是removeChild,先回到父节点,在从父节点上移除要移除的节点。

// 为了在IE和其它浏览器下都能正常使用,取上一层的父结点,然后remove。
node.parentNode.removeChild(node);

24.expression

  【问题描述】:IE下样式支持计算表达式expression,但其它浏览器不支持,而且IE以后高版本也可能不再支持这种样式,所以不允许使用。下面是通常使用的情况:

<div id=”content”
style=’height:expression(document.body.offsetHeight-80)”></div>

  【兼容办法】:去掉样式设置,将其写到函数中,分别在页面加载完毕和页面尺寸发生变化时执行。如下:

$(function(){
$(“#content”).height($(document.body).height()-80);
}) $(window).resize(function(){
$(“#content”).height($(document.body).height()-80);
});

25.Cursor

  【问题描述】:Cursor的hand属性只有IE支持,其它浏览器没有效果,如:

<div style=”cursor:hand”></div>

  【兼容办法】:统一用pointer值,如:

<div style=”cursor: pointer”></div>

26.CSS透明问题

  【问题描述】:IE支持但其它浏览器不支持的透明样式如下:

<div style="filter:progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=20);width:200px;height:200px;background-color:Blue">ddddd</div>

  其它浏览器支持但IE不支持的透明样式如下:

<div style="opacity:0.2;width:200px;height:200px;background-color:Blue">ddddd</div>

  【兼容办法】:利用”!important”来设置元素的样式。Safari,FireFox,Chrome对于”!important”会自动优先解析,然而IE则会忽略。如下

<div style="filter:progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=20);width:200px;height:200px;background-color:Blue;!important; opacity:0.2">ddddd</div>

27.pixelHeight\pixelWidth

  【问题描述】:pixelHeight\pixelWidth是元素的高度和宽度样式,通常获取方法是:

obj.style.pixelWidth;

obj.style.pixelHeight;

  IE,Safari,Chrome都支持此样式,返回的值是整数,FireFox不支持

  【兼容办法】:所有浏览器都支持obj.style.height,但返回的值是带单位的,如“100px”。可以用如下方法来获取:

parseInt(obj.style.height)

28.noWrap

  【问题描述】:nowrap 属性是被废弃的属性。

  【兼容办法】:使用 CSS 规则 white-space:nowrap 代替这个属性。

29.CSSfloat属性

  【问题描述】:Javascript访问一个给定CSS 值的最基本句法是:object.style.property,但部分CSS属性跟Javascript中的保留字命名相同,如"float","for","class"等,不同浏览器写法不同。

  在IE中这样写:

document.getElementById("header").style.styleFloat = "left";

  在其它浏览器中这样写:

document.getElementById("header").style.cssFloat = "left";

  【兼容办法】:兼容方法是在写之前加一个判断,判断浏览器是否是IE:

if(jQuery.browser.msie){
document.getElementById("header").style.styleFloat = "left";
}
else{
document.getElementById("header").style.cssFloat = "left";
}

30.访问label标签中的for

  【问题描述】:for 属性规定 label 与哪个表单元素绑定。在IE中这样写:

var myObject = document.getElementById("myLabel");

var myAttribute = myObject.getAttribute("htmlFor");

  在Firefox中这样写:

var myObject = document.getElementById("myLabel");

var myAttribute = myObject.getAttribute("for");

  【兼容办法】:判断浏览器是否是IE:

var myObject = document.getElementById("myLabel");
if(jQuery.browser.msie){
var myAttribute = myObject.getAttribute("htmlFor");
}
else{
var myAttribute = myObject.getAttribute("for");
}

31.访问和设置class属性

  【问题描述】:同样由于class是Javascript保留字的原因,这两种浏览器使用不同的 JavaScript 方法来获取这个属性。

  IE8.0之前的所有IE版本的写法:

var myObject = document.getElementById("header");

var myAttribute = myObject.getAttribute("className"); 

  适用于IE8.0 以及 firefox的写法:

var myObject = document.getElementById("header");

var myAttribute = myObject.getAttribute("class");

  另外,在使用setAttribute()设置Class属性的时候,两种浏览器也存在同样的差异。

  setAttribute("className",value);这种写法适用于IE8.0之前的所有IE版本,注意:IE8.0也不支持"className"属性了。setAttribute("class",value);适用于IE8.0 以及 firefox。

  【兼容办法】:

  1.两种都写上:

1 //设置header的class为classValue
2 var myObject = document.getElementById("header");
3
4 myObject.setAttribute("class","classValue");
5
6 myObject.setAttribute("className","classValue");

  2.IE和FF都支持object.className,所以可以这样写:

var myObject = document.getElementById("header");

myObject.className="classValue";//设置header的class为classValue

  3.先判断浏览器类型,再根据浏览器类型采用对应的写法。

32.对象宽高赋值问题

  【问题描述】:非IE浏览器中中类似 obj.style.height = imgObj.height 的语句无效,必须加上’px’。

  【兼容办法】:给元素高度宽度附值是,统一都加上’px’,如:

obj.style.height = imgObj.height + ‘px’;

33.鼠标位置

  【问题描述】:IE下,even对象有x、y属性,但是没有pageX、pageY属性;Firefox下,even对象有pageX、pageY属性,但是没有x、y属性;Safari、Chrome中x、y属性和pageX、pageY都有。

  【兼容办法】:使用mX = event.x ? event.x : event.pageX;来代替。复杂点还要考虑绝对位置。

function getAbsPoint(e){
var x = e.offsetLeft, y = e.offsetTop;
while (e = e.offsetParent) {
x += e.offsetLeft;
y += e.offsetTop;
}
alert("x:" + x + "," + "y:" + y);
}

34.event.srcElement 

  【问题描述】:IE下,event对象有srcElement属性,但是没有target属性;其它浏览器下,even对象有target属性,但是没有srcElement属性。

  【兼容办法】:

var obj = event.srcElement?event.srcElement:event.target;

35.关于<input type="file">

  (1) 在safari浏览器下的此控件没有文本框,只有一个“选取文件”的按钮,所有也没有onblur事件,如果在<input type="file" onblur="alert(0);">中用到了需要做特殊处理。

  (2) 在FF浏览器下用<input type="file" name="file"> 上传文件后取file.value时只能去掉文件名而没有文件路径,不能实现预览的效果,可以用document.getElementById("pic").files[0].getAsDataURL();取到加密后的路径,此路径只有在FF下才可以解析。

  (3) 在safari浏览器下用<input type="file" name="file"> 上传文件后取file.value时只能去掉文件名而没有文件路径,不能实现预览的效果。建议使用上传后的路径预览。

36.jquery对象是否为空

  jquery对象是否为空判断,用length判断一下

$("#hidTitle").length>0

  IOS设计模式浅析

数据结构和算法之:图的深度优先和广度优先遍历及其Java实现

 

图的遍历,所谓遍历,即是对结点的访问。

一个图有那么多个结点,如何遍历这些结点,需要特定策略,一般有两种访问策略,深度优先遍历和广度优先遍历。
 
深度优先遍历:
深度优先遍历,从初始访问结点出发,我们知道初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点。总结起来可以这样说:每次都在访问完当前结点后首先访问当前结点的第一个邻接结点。
我们从这里可以看到,这样的访问策略是优先往纵向挖掘深入,而不是对一个结点的所有邻接结点进行横向访问。
 
具体算法表述如下:
1,访问初始结点v,并标记结点v为已访问。
2,查找结点v的第一个邻接结点w。
3,若w存在,则继续执行4,否则算法结束。
4,若w未被访问,对w进行深度优先遍历递归(即把w当做另一个v,然后进行步骤123)。
5,查找结点v的w邻接结点的下一个邻接结点,转到步骤3。
 
例如下图,其深度优先遍历顺序为 1->2->4->8->5->3->6->7
aaarticlea/png;base64,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" alt="" />
 
广度优先遍历:
类似于一个分层搜索的过程,广度优先遍历需要使用一个队列以保持访问过的结点的顺序,以便按这个顺序来访问这些结点的邻接结点。
 
具体算法表述如下:
1,访问初始结点v并标记结点v为已访问。
2,结点v入队列
3,当队列非空时,继续执行,否则算法结束。
4,出队列,取得队头结点u。
5,查找结点u的第一个邻接结点w。
6,若结点u的邻接结点w不存在,则转到步骤3;否则循环执行以下三个步骤:
① 若结点w尚未被访问,则访问结点w并标记为已访问。
②结点w入队列
③查找结点u的继w邻接结点后的下一个邻接结点w,转到步骤6。
 
如上文的图,其广度优先算法的遍历顺序为:1->2->3->4->5->6->7->8
 
深度优先遍历和广度优先遍历的Java实现
 
前面一文http://www.cnblogs.com/breakpoint/p/3477703.html已经实现过邻接矩阵图类AMWGraph.java,在这里还是把这个类再贴一遍好了。在原先类的基础上增加了两个遍历的函数,分别是depthFirstSearch()和broadFirstSearch()。
  1 package com.ds;
2
3 import java.util.ArrayList;
4 import java.util.LinkedList;
5
6 /**
7 * @description 图的邻接矩阵图类
8 * @author 等待飞鱼
9 * @time 2013.12.17
10 */
11 public class AMWGraph {
12
13 private ArrayList vertexList;//存储点的链表
14 private int[][] edges;//邻接矩阵,用来存储边
15 private int numOfEdges;//边的数目
16
17 public AMWGraph(int n)
18 {
19 //初始化矩阵,一维数组,和边的数目
20 edges=new int[n][n];
21 vertexList=new ArrayList(n);
22 numOfEdges=0;
23 }
24 //得到结点的个数
25 public int getNumOfVertex(){
26 return vertexList.size();
27 }
28 //得到边的数目
29 public int getNumOfEdges()
30 {
31 return numOfEdges;
32 }
33 //返回结点i的数据
34 public Object getValueByIndex(int i)
35 {
36 return vertexList.get(i);
37 }
38 //返回v1,v2的权值
39 public int getWeight(int v1,int v2)
40 {
41 return edges[v1][v2];
42 }
43 //插入结点
44 public void insertVertex(Object vertex)
45 {
46 vertexList.add(vertexList.size(),vertex);
47 }
48 //插入结点
49 public void insertEdge(int v1,int v2,int weight){
50 edges[v1][v2]=weight;
51 numOfEdges++;
52 }
53 //删除结点
54 public void deleteEdge(int v1,int v2)
55 {
56 edges[v1][v2]=0;
57 numOfEdges--;
58 }
59 //得到第一个邻接结点的下标
60 public int getFirstNeighbor(int index)
61 {
62 for(int j=0;j<vertexList.size();j++)
63 {
64 if (edges[index][j]>0)
65 {
66 return j;
67 }
68 }
69 return -1;
70 }
71 //根据前一个邻接结点的下标来取得下一个邻接结点
72 public int getNextNeighbor(int v1,int v2)
73 {
74 for (int j=v2+1;j<vertexList.size();j++)
75 {
76 if (edges[v1][j]>0)
77 {
78 return j;
79 }
80 }
81 return -1;
82 }
83 //私有函数,深度优先遍历
84 private void depthFirstSearch(boolean[] isVisited,int i)
85 {
86 //首先访问该结点,在控制台打印出来
87 System.out.print(getValueByIndex(i)+" ");
88 //置该结点为已访问
89 isVisited[i]=true;
90
91 int w=getFirstNeighbor(i);//
92 while (w!=-1)
93 {
94 if (!isVisited[w])
95 {
96 depthFirstSearch(isVisited,w);
97 }
98 w=getNextNeighbor(i, w);
99 }
100 }
101 //对外公开函数,深度优先遍历,与其同名私有函数属于方法重载
102 public void depthFirstSearch()
103 {
104 boolean[] isVisited=new boolean[getNumOfVertex()];//记录结点是否已经被访问的数组
105 for (int i=0;i<getNumOfVertex();i++)
106 {
107 isVisited[i]=false;//把所有节点设置为未访问
108 }
109 for(int i=0;i<getNumOfVertex();i++)
110 {
111 //因为对于非连通图来说,并不是通过一个结点就一定可以遍历所有结点的。
112 if (!isVisited[i]){
113 depthFirstSearch(isVisited,i);
114 }
115 }
116 }
117 //私有函数,广度优先遍历
118 private void broadFirstSearch(boolean[] isVisited,int i)
119 {
120 int u,w;
121 LinkedList queue=new LinkedList();
122
123 //访问结点i
124 System.out.print(getValueByIndex(i)+" ");
125 isVisited[i]=true;
126 //结点入队列
127 queue.addlast(i);
128 while (!queue.isEmpty())
129 {
130 u=((Integer)queue.removeFirst()).intValue();
131 w=getFirstNeighbor(u);
132 while(w!=-1){
133 if(!isVisited[w]){
134 //访问该结点
135 System.out.print(getValueByIndex(w)+" ");
136 //标记已被访问
137 isVisited[w]=true;
138 //入队列
139 queue.addLast(w);
140 }
141 //寻找下一个邻接结点
142 w=getNextNeighbor(u, w);
143 }
144 }
145 }
146 //对外公开函数,广度优先遍历
147 public void broadFirstSearch()
148 {
149 boolean[] isVisited=new boolean[getNumOfVertex()];
150 for (int i=0;i<getNumOfVertex();i++)
151 {
152 isVisited[i]=false;
153 }
154 for(int i=0;i<getNumOfVertex();i++)
155 {
156 if(!isVisited[i])
157 {
158 broadFirstSearch(isVisited, i);
159 }
160 }
161 }
162 }

上面的public声明的depthFirstSearch()和broadFirstSearch()函数,是为了应对当该图是非连通图的情况,如果是非连通图,那么只通过一个结点是无法完全遍历所有结点的。

下面根据上面用来举例的图来构造测试类:

package com.ds;

public class TestSearch {

    public static void main(String args[])
{
int n=8,e=9;//分别代表结点个数和边的数目
String labels[]={"1","2","3","4","5","6","7","8"};//结点的标识
AMWGraph graph=new AMWGraph(n);
for(String label:labels){
graph.insertVertex(label);//插入结点
}
//插入九条边
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.insertEdge(3, 7, 1);
graph.insertEdge(4, 7, 1);
graph.insertEdge(2, 5, 1);
graph.insertEdge(2, 6, 1);
graph.insertEdge(5, 6, 1);
graph.insertEdge(1, 0, 1);
graph.insertEdge(2, 0, 1);
graph.insertEdge(3, 1, 1);
graph.insertEdge(4, 1, 1);
graph.insertEdge(7, 3, 1);
graph.insertEdge(7, 4, 1);
graph.insertEdge(4, 2, 1);
graph.insertEdge(5, 2, 1);
graph.insertEdge(6, 5, 1); System.out.println("深度优先搜索序列为:");
graph.depthFirstSearch();
System.out.println();
System.out.println("广度优先搜索序列为:");
graph.broadFirstSearch();
}
}

运行后控制台输出如下

aaarticlea/png;base64,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" alt="" />

如果有什么想说的,请给我留言,谢谢!

 
 
 
标签: 算法
循自然之道,抚浮躁之心

ASP.NET Web API中的JSON和XML序列化的更多相关文章

  1. 【ASP.NET Web API教程】6.2 ASP.NET Web API中的JSON和XML序列化

    谨以此文感谢关注此系列文章的园友!前段时间本以为此系列文章已没多少人关注,而不打算继续下去了.因为文章贴出来之后,看的人似乎不多,也很少有人对这些文章发表评论,而且几乎无人给予“推荐”.但前几天有人询 ...

  2. Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET W ...

  3. ASP.NET Web API中的参数绑定总结

    ASP.NET Web API中的action参数类型可以分为简单类型和复杂类型. HttpResponseMessage Put(int id, Product item) id是int类型,是简单 ...

  4. 【ASP.NET Web API教程】4.3 ASP.NET Web API中的异常处理

    原文:[ASP.NET Web API教程]4.3 ASP.NET Web API中的异常处理 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内 ...

  5. ASP.NET Web API中实现版本的几种方式

    在ASP.NET Web API中,当我们的API发生改变,就涉及到版本问题了.如何实现API的版本呢? 1.通过路由设置版本 最简单的一种方式是通过路由设置,不同的路由,不同的版本,不同的contr ...

  6. ASP.NET Web API 中的返回数据格式以及依赖注入

    本篇涉及ASP.NET Web API中的返回数据合适和依赖注入. 获取数据 public IEnumerable<Food> Get() { var results = reop.Get ...

  7. Asp.Net Web Api中使用Swagger

    关于swagger 设计是API开发的基础.Swagger使API设计变得轻而易举,为开发人员.架构师和产品所有者提供了易于使用的工具. 官方网址:https://swagger.io/solutio ...

  8. 在 ASP.NET Web API 中使用 Attribute 统一处理异常

    并非所有的异常都需要 try-catch 进行重复的处理,这会导致大量的重复性代码,一旦后续系统出现异常处理机制的修改,随着代码量增多,修改也会变的更加困难. ASP.NET Web API 中特别增 ...

  9. 利用查询条件对象,在Asp.net Web API中实现对业务数据的分页查询处理

    在Asp.net Web API中,对业务数据的分页查询处理是一个非常常见的接口,我们需要在查询条件对象中,定义好相应业务的查询参数,排序信息,请求记录数和每页大小信息等内容,根据这些查询信息,我们在 ...

随机推荐

  1. js中frame的操作问题

    这里以图为例,在这里把frame之间的互相操作简单列为:1变量2方法3页面之间元素的互相获取. A  首先从 父(frameABC)------->子(frameA,frameB,frameC) ...

  2. 第一次测试HTML和CSS

    1.HTML(Hyper Text Markup Languange)超文本标记语言.HTML文件扩展名通常是:htm和html. <html> <head> <titl ...

  3. 经典算法题每日演练——第十一题 Bitmap算法

    原文:经典算法题每日演练--第十一题 Bitmap算法 在所有具有性能优化的数据结构中,我想大家使用最多的就是hash表,是的,在具有定位查找上具有O(1)的常量时间,多么的简洁优美, 但是在特定的场 ...

  4. IMSDroid遇到注册问题(蘼1S 计3等一下 Android4.4)

    最近的研究视频通话,开源项目IMSDroid编译测试,这实在是不幸的,饭1 Android4.1和大米3 Android4.4该系统不是对生命和死亡登记.... .后来通过大神日志分析和建议.发现改变 ...

  5. 2014鞍山直播比赛H称号HDU5077(DFS修剪+通过计)

    NAND Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Sub ...

  6. Android[安德鲁斯] 文本Air Video 远程播放电脑视频

    苹果iOS下列.目前应用Air Video,能力iOS由Wifi远程直接播放电脑视频,无需看视频复制到手机.非常好用!最近使用Android打电话.展望类别似应用,找了很长一段时间没有找到.在仔细的思 ...

  7. jsp的&lt;%%&gt;

    于jsp于 可以使用<% %> 嵌入java代码,简称jsp文字. 可以使用<% -- -- %> 凝视,这是jsp注视 可以使用<%! %> 声明全局变量 版权声 ...

  8. Swift入门教程:基本语法(五)

    断言 断言是一种实时检测条件是否为true的方法 如果条件为true,那么代码继续执行 如果条件为false,就抛出错误信息,直接终止程序的运行   断言的用法 使用全局的assert函数 passe ...

  9. Android利用CountDownTimer类实现倒计时功能

    public class MainActivity extends Activity { private MyCount mc; private TextView tv; @Override publ ...

  10. 基于Bootstrap的Asp.net Mvc 分页

    基于Bootstrap的Asp.net Mvc 分页的实现 最近写了一个mvc 的 分页,样式是基于 bootstrap 的 ,提供查询条件,不过可以自己写样式根据个人的喜好,以此分享一下.首先新建一 ...