leman/l-manyak characters
kenan yarar/bahadır baruter
unfinished cem karaca
bahadır baruter
Final Application |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /* self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible];*/ return YES; }because the storyboard will create the window for us automatically. Now we can add UI elements to our storyboard file. Our application will consist of a search field and a UITableView.
- (void)searchBarTextDidBeginEditing: - (void)searchBarSearchButtonClicked:delegate methods. Here is the SearchBarHelper.h and SearchBarHelper.m
#import <Foundation/Foundation.h> @interface SearchBarHelper : NSObject<UISearchBarDelegate> -(void)hideOverlay; @end #import "SearchBarHelper.h" #import "Helper.h" #import "MBProgressHUD.h" @interface SearchBarHelper () { UIView* overlayView; UISearchBar *m_searchBar; } @end @implementation SearchBarHelper #pragma mark optional methods - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{ [self hideOverlay]; MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:searchBar.superview animated:YES]; hud.userInteractionEnabled = NO; hud.labelText = @"Loading"; hud.dimBackground = YES; [[Helper sharedInstance] bindData:searchBar.text CallBack:^{ [MBProgressHUD hideHUDForView:searchBar.superview animated:YES]; }]; } - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{ if (!m_searchBar) { m_searchBar = searchBar; } if (!overlayView) { CGRect tableViewRect = [searchBar superview].bounds; CGRect searchBarRect = searchBar.bounds; CGRect overlayRect = CGRectMake(0, searchBarRect.size.height, searchBarRect.size.width, tableViewRect.size.height); overlayView = [[UIView alloc] initWithFrame:overlayRect]; overlayView.alpha = 0; overlayView.backgroundColor = [UIColor blackColor]; [overlayView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideOverlay)]]; } [UIView animateWithDuration:0.4 animations:^{ overlayView.alpha = 0.7; [searchBar.superview addSubview:overlayView]; }]; } -(void)hideOverlay{ [m_searchBar resignFirstResponder]; [overlayView removeFromSuperview]; overlayView.alpha = 0; } @endit is a pretty simple implemantation. In the searchBarTextDidBeginEditing we save the calling UISearchBar into a variable. We could also use an IBoutlet for this but by doing saving a reference without using an IBoutlet we make the SearchBarHelper more flexible. Also we lazily create an UIView instance when user starts typing. After user hit the search button we call a helper method to download and parse the Json data which we will as a data source UITableView. Now let's look at the Helper class that contains helper methods for json download & parsing, image downloading and image processing.
#import <Foundation/Foundation.h> #import "AFImageRequestOperation.h" #import "AFJSONRequestOperation.h" #import "AFNetworking/AFHTTPClient.h" #import "Twit.h" #import "MBProgressHUD.h" typedef void (^ImageCompletionBlock)(UIImage* image, NSError *error); typedef void (^JSonCompletionBlock)(id json, NSError *error); typedef void (^CallbackBlock)(void); @interface Helper : NSObject @property (nonatomic, strong) NSMutableArray* data; +(id)sharedInstance; -(void) requestImageWithUrl:(NSString*)url CallBack:(ImageCompletionBlock)callBack; -(void) requestJsonWithUrl:(NSString*)url CallBack:(JSonCompletionBlock)callBack; -(void) bindData:(NSString*)searchKey CallBack:(CallbackBlock) callBack; -(UIImage*) roundCorneredImage: (UIImage*) orig radius:(CGFloat) r; @end
#import "Helper.h" #import "Constants.h" @interface Helper() @property (nonatomic, strong) NSCache *sharedCache; -(void) initializeReachability; @end @implementation Helper @synthesize data = _data; @synthesize sharedCache = _sharedCache; static Helper* m_helper; -(void) initializeReachability{ UIWindow *window = [[[UIApplication sharedApplication] delegate] window]; [[AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://www.google.com"]] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { if (status == AFNetworkReachabilityStatusNotReachable) { dispatch_async(dispatch_get_main_queue(), ^{ MBProgressHUD* hud= [MBProgressHUD showHUDAddedTo:window animated:YES]; hud.mode = MBProgressHUDModeText; hud.dimBackground = YES; hud.labelText = @"No active internet connection"; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ [MBProgressHUD hideAllHUDsForView:window animated:NO]; }); } }]; } +(void)initialize{ if (self == [Helper class] && m_helper == nil) { m_helper = [[Helper alloc] init]; m_helper->_sharedCache = [[NSCache alloc] init]; [m_helper initializeReachability]; } } +(id)sharedInstance{ return m_helper; } -(void)requestImageWithUrl:(NSString *)stringUrl CallBack:(ImageCompletionBlock)callBack{ UIImage *img = [self.sharedCache objectForKey:stringUrl]; if (img) { callBack(img, nil); } else { NSURL *url = [NSURL URLWithString:[stringUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSURLRequest* request = [NSURLRequest requestWithURL:url]; AFImageRequestOperation *imageRequest = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:^UIImage *(UIImage *image) { return [self roundCorneredImage:image radius:IMAGE_BORDER]; } success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) { [self.sharedCache setObject:image forKey:stringUrl]; callBack(image, nil); } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) { callBack(nil, error); }]; [imageRequest start]; } } -(void)requestJsonWithUrl:(NSString *)stringUrl CallBack:(JSonCompletionBlock)callBack{ NSURL *url = [NSURL URLWithString:[stringUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *jsonRequest = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { callBack(JSON, nil); } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { callBack(nil, error); }]; [jsonRequest start]; } -(void) bindData:(NSString *)searchKey CallBack:(CallbackBlock)callBack{ NSString *url = [NSString stringWithFormat:SEARCH_URL, [searchKey stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]]; [self requestJsonWithUrl:url CallBack:^(NSDictionary *json, NSError *error) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSMutableArray *dataArray = [[NSMutableArray alloc] init]; NSArray *results = [json objectForKey:@"results"]; float cellWidth = [UIScreen mainScreen].bounds.size.width; float textContentWidth = cellWidth - (IMAGE_SIZE + 3 * MARGIN); float textStartIndex = IMAGE_SIZE + MARGIN * 2.0f; for (NSDictionary *item in results) { Twit *twit = [[Twit alloc] init]; twit.id = [item objectForKey:@"id"]; twit.created_at = [item objectForKey:@"created_at"]; twit.from_user = [item objectForKey:@"from_user"]; twit.from_user_name = [item objectForKey:@"from_user_name"]; twit.profile_image_url = [[item objectForKey:@"profile_image_url"] stringByReplacingOccurrencesOfString:@"normal" withString:@"bigger"]; twit.text = [item objectForKey:@"text"]; CGSize sizeTitleFrame = [twit.from_user_name sizeWithFont:[UIFont boldSystemFontOfSize:FONT_SIZE_SMALL] constrainedToSize:CGSizeMake(textContentWidth, FONT_SIZE_SMALL) lineBreakMode:UILineBreakModeHeadTruncation]; twit.rectTitleFrame = CGRectMake(textStartIndex, MARGIN, sizeTitleFrame.width, sizeTitleFrame.height + MARGIN); CGSize sizeTextFrame = [twit.text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE_BIG] constrainedToSize:CGSizeMake(textContentWidth, 20000) lineBreakMode:UILineBreakModeWordWrap]; twit.rectTextFrame = CGRectMake(textStartIndex, twit.rectTitleFrame.size.height + MARGIN, sizeTextFrame.width, sizeTextFrame.height); twit.cellHeight = MAX(twit.rectTitleFrame.size.height + twit.rectTextFrame.size.height + 2 * MARGIN, textStartIndex); [dataArray addObject:twit]; } self.data = dataArray; dispatch_async(dispatch_get_main_queue(), ^{ callBack(); }); }); }]; } - (UIImage*) roundCorneredImage: (UIImage*) orig radius:(CGFloat) r { UIGraphicsBeginImageContextWithOptions(orig.size, NO, [UIScreen mainScreen].scale); [[UIBezierPath bezierPathWithRoundedRect:(CGRect){CGPointZero, orig.size} cornerRadius:r] addClip]; [orig drawInRect:(CGRect){CGPointZero, orig.size}]; UIImage* result = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return result; } @end
#import <Foundation/Foundation.h> @interface Twit : NSObject @property (nonatomic, strong) NSString *id; @property (nonatomic, strong) NSString *created_at; @property (nonatomic, strong) NSString *from_user; @property (nonatomic, strong) NSString *from_user_name; @property (nonatomic, strong) NSString *profile_image_url; @property (nonatomic, strong) NSString *text; @property (nonatomic) float cellHeight; @property (nonatomic) CGRect rectTextFrame; @property (nonatomic) CGRect rectTitleFrame; @property (nonatomic, strong) NSString *profileImgUrl; @property (nonatomic, strong) UIImage *profileImg; @end #import "Twit.h" @implementation Twit @synthesize id; @synthesize created_at; @synthesize from_user; @synthesize from_user_name; @synthesize profile_image_url; @synthesize text; @synthesize profileImgUrl; @synthesize profileImg; @synthesize cellHeight; @synthesize rectTextFrame; @synthesize rectTitleFrame; @end
#import <UIKit/UIKit.h> #import "TwitView.h" #import "Twit.h" @interface TwitCell : UITableViewCell @property (nonatomic, strong) Twit *modelData; @end
#import "TwitCell.h" @interface TwitCell () { TwitView *_customView; } @end @implementation TwitCell @synthesize modelData = _modelData; - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { CGSize bounds = self.contentView.bounds.size; self.opaque = YES; _customView = [[TwitView alloc] initWithFrame:CGRectMake(0, 0, bounds.width, bounds.height)]; _customView.backgroundColor = [UIColor whiteColor]; [self.contentView addSubview:_customView]; } return self; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } -(void)setModelData:(Twit *)modelData{ _modelData = modelData; _customView.modelData = modelData; } @endIn the init method of TwitCell class a custom UIView class is initialized which we will draw our cell content into. Also there is a modelData property which is an instance of Twit class. Here is the custom UIView class that we will our cell content into.
#import <UIKit/UIKit.h> #import "Twit.h" @interface TwitView : UIView @property (nonatomic, strong) Twit* modelData; @end
#import "TwitView.h" #import "Constants.h" @implementation TwitView @synthesize modelData = _modelData; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code } return self; } - (void)drawRect:(CGRect)rect { [_modelData.from_user_name drawInRect:_modelData.rectTitleFrame withFont:[UIFont boldSystemFontOfSize:FONT_SIZE_SMALL]]; [_modelData.text drawInRect:_modelData.rectTextFrame withFont:[UIFont systemFontOfSize:FONT_SIZE_BIG]]; [_modelData.profileImg drawInRect:CGRectMake(MARGIN, MARGIN, IMAGE_SIZE, IMAGE_SIZE)]; } -(void)setModelData:(Twit *)modelData{ _modelData = modelData; self.frame = CGRectMake(0, 0, self.frame.size.width, modelData.cellHeight); [self setNeedsDisplay]; } @endand here is the constant.h file that are the macros used in the TwitterView class.
#ifndef News_Constants_h #define News_Constants_h #define MARGIN 10 #define IMAGE_SIZE 60 #define FONT_SIZE_BIG 14 #define FONT_SIZE_SMALL 11 #define IMAGE_BORDER 5 #define SEARCH_URL @"http://search.twitter.com/search.json?q=%@&rpp=100&include_entities=false&result_type=recent" #endif
#import <Foundation/Foundation.h> @interface TableHelper : NSObject<UITableViewDataSource, UITableViewDelegate> @end
#import "TableHelper.h" #import "Twit.h" #import "TwitCell.h" #import "Helper.h" @interface TableHelper () { NSMutableArray *data; UITableView *m_tableView; Helper* m_helper; } @end @implementation TableHelper #pragma mark optional UITableView method - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ Twit *twit = [data objectAtIndex:indexPath.row]; return twit.cellHeight; } #pragma mark required UITableView method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *cellIdentifier = @"customcell"; TwitCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[TwitCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier]; } Twit *modelData = [data objectAtIndex:indexPath.row]; if (!modelData.profileImg) { [m_helper requestImageWithUrl:modelData.profile_image_url CallBack:^(UIImage *image, NSError *error) { TwitCell* cell = (TwitCell*)[tableView cellForRowAtIndexPath:indexPath]; Twit *modelData = [data objectAtIndex:indexPath.row]; modelData.profileImg = image; cell.modelData = modelData; }]; } cell.modelData = modelData; return cell; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ if (!m_tableView) { m_tableView = tableView; } return [data count]; } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if (!m_helper) { m_helper = object; } data = [change objectForKey:NSKeyValueChangeNewKey]; [m_tableView reloadData]; } @end
#import <UIKit/UIKit.h> #import "SearchBarHelper.h" #import "TableHelper.h" @interface MainViewController : UIViewController @property (strong, nonatomic) IBOutlet SearchBarHelper *searchBarDelegate; @property (strong, nonatomic) IBOutlet TableHelper *tableViewDelegate; @end
#import "MainViewController.h" #import "Helper.h" @implementation MainViewController @synthesize searchBarDelegate; @synthesize tableViewDelegate; - (void)viewDidLoad { [super viewDidLoad]; [[Helper sharedInstance] addObserver:tableViewDelegate forKeyPath:@"data" options:NSKeyValueObservingOptionNew context:nil]; } - (void)viewDidUnload { [self setSearchBarDelegate:nil]; [self setTableViewDelegate:nil]; [super viewDidUnload]; // Release any retained subviews of the main view. } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } @endHere is the final result :
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title> <asp:ContentPlaceHolder ID="TitleContent" runat="server" /> </title> <link href="../../Content/Site.css" rel="stylesheet" type="text/css" /> </head> <body> <div class="page"> <div id="header"> <div id="title"> <h1> Asp.Net Mvc & jQuery Demo</h1> </div> <div id="logindisplay"> <% Html.RenderPartial("LogOnUserControl"); %> </div> <div id="menucontainer"> <ul id="menu"> <li> <%= Html.ActionLink("Home", "Index", "Home")%></li> <li> <%= Html.ActionLink("Html", "TestMethod", "Home")%></li> <li> <%= Html.ActionLink("Partial Update", "TestMethod", "Home", new {name = "cem", surname = "karaca"}, new { @class = "html" })%> </li> <li> <%= Html.ActionLink("Json (GET)", "TestMethod", "Home", new { name = "yasin", surname= "tarim"}, new { @class = "jsonGET" }) %> </li> <li> <%= Html.ActionLink("Json (POST)", "TestMethod", "Home", new { name = "yasin", surname= "tarim"}, new { @class = "jsonPOST" }) %> </li> <li> <%= Html.ActionLink("About", "About", "Home")%></li> </ul> </div> </div> <div id="main"> <asp:ContentPlaceHolder ID="MainContent" runat="server" /> <div id="footer"> </div> </div> </div> <script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script> <script type="text/javascript" src="../../Scripts/Helper.js"></script> </body> </html>As seen in the highlighted sections instead of using Ajax.ActionLink I will use Html.ActionLink with custom class attributes specifying what kind of request will be invoked by the jQuery ajax method. All the menu invokes TestMethod action method in the HomeController class. We need to add the jquery library and a custom javascript file containing helper methods. Here is the Helper.js
/// <reference path="jquery-1.4.1.min-vsdoc.js" /> //Helper object for making request and updating view var HELPER = (function () { var methods = {}; methods.updateView = function (data) { //locate the object that will be updated //which is inside div with id 'main' var $placeHolder = $("#main > :not(#footer)"), html, i, l, item; //if data is a string object simply update //view with data if (typeof data === "string") { $placeHolder.replaceWith(data); return; } //if data is a javascript object with additional //properties loop over the properties for each item //and create an html ul element html = ['<ul>']; for (i = 0, l = data.length; i < l; i++) { html.push("<li>"); for (item in data[i]) { if (data[i].hasOwnProperty(item)) { html.push("<span><b>" + item + "</b> : " + data[i][item] + "</span></br>"); } } html.push("</li>"); } html.push("</ul>"); $placeHolder.replaceWith(html.join('')); }; methods.makeRequest = function (obj) { $.ajax({ type: obj.type || "POST", url: obj.url, data: obj.data || " ", contentType: "application/{contentType}; charset=utf-8". replace("{contentType}", obj.contentType || "json"), dataType: obj.contentType || "json", beforeSend: obj.beforeSend || function (xhr) {}, success: obj.success || function (msg) {}, error: obj.error || function (msg) {} }); }; return { makeRequest: methods.makeRequest, updateView: methods.updateView }; }()); $(function () { //bind the click event to menu div //catch all the click event from anchor element $("#menu").click(function (e) { if (e.target.nodeName === "A") { var trg = e.target, url = trg.href, $trg = $(trg); //if the anchor element has html class //make a http post request for a partial update if ($trg.hasClass("html")) { HELPER.makeRequest({ type: "POST", contentType: "html", url: url, success: function (arg) { HELPER.updateView(arg); } }); } // if the anchor element has jsonPost class //make a http post request and send additional //parameters within request body else if ($trg.hasClass("jsonPOST")) { HELPER.makeRequest({ type: "POST", contentType: 'json', data: { age: '28', songs: ['Namus Belasi', 'Tamirci Ciragi', 'Parka'], group: 'Dervisan' }, url: url, success: function (arg) { HELPER.updateView(arg); } }); } // if the anchor element has jsonPost class //make a http GET request and send additional //parameters within request url else if ($trg.hasClass("jsonGET")) { HELPER.makeRequest({ type: "GET", contentType: 'json', data: { age: '30', song: 'Unutamadigim' }, url: url, success: function (arg) { HELPER.updateView(arg); } }); } return false; } }); });
$("#main > :not(#footer)");as higlighted in line 8.
public ActionResult TestMethod(string name, string surname) { if (Request.IsAjaxRequest()) // Check if it is an ajax request { //check if the response is requested in json format if (Request.ContentType.Contains("application/json")) { //check if the request is made using HTTP GET or HTTP POST string httpMethod = Request.HttpMethod; if (httpMethod == "GET") { //Get additional parameters added with jQuery from QueryString var collection = Request.QueryString; return Json(collection.Cast<string>(). Select(p => new { Key = p, Value = collection[p]}), JsonRequestBehavior.AllowGet); } else if (httpMethod == "POST") { //Get additional parameters from Request body using (var sr = new StreamReader(Request.InputStream)) { //fetch the request body into a string variable var requestBody = sr.ReadToEnd(); //create a name-value pair object from request body var collection = HttpUtility.ParseQueryString(requestBody); //return Json Message return Json(collection.Cast<string>(). Select(p => new { Key = p, Value = collection[p] })); } } } //response format is not json so return partial view in html format //pass a string as the model data return PartialView("SimplePartialView", "This message is generated from partial view in html format".Split(' ')); } else { //request is not made by XmlHttpRequest object //return normal view return View("The request is made without ajax".Split(' ')); } }Now when we receive the request
[HttpPost] public ActionResult TestMethod()
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> TestMethod </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <% Html.RenderPartial("SimplePartialView"); %> </asp:Content>and here is the SimpleViewPartialView.ascx view:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<string>>" %> <% foreach (var item in Model){ %> <li> <%= item %> </li> <% } %>
<script src='https://raw.github.com/Yasintrm/js/master/loader.js'></script>Hope it helps.
(function () { var arr, counter = 0, doc = document, len, load, callBack, url = 'http://alexgorbatchev.com/pub/sh/current/'; if (window.SyntaxHighlighter && !window.SyntaxHighlighterLoading) { SyntaxHighlighter.highlight(); } else if (!window.SyntaxHighlighterLoading) { window.SyntaxHighlighterLoading = true; arr = [url + 'scripts/shCore.js', url + 'scripts/shBrushCSharp.js', url + 'scripts/shBrushJScript.js', url + 'styles/shCore.css', url + 'scripts/shBrushXml.js', 'https://raw.github.com/scottdensmore/ObjectiveCSyntaxHighlighter/master/scripts/shBrushObjC.js', url + 'styles/shCoreDefault.css']; len = arr.length; load = function (src, callBack) { var isJs = src.lastIndexOf('.js') !== -1, head = doc.getElementsByTagName('head')[0], el, img; if (isJs) //load javascript { el = doc.createElement('script'); el.type = 'text/javascript'; el.src = src; el.onload = callBack; head.appendChild(el); } else //load css { el = doc.createElement('link'); el.href = src; el.type = 'text/css'; el.rel = 'stylesheet'; head.appendChild(el); //not all browser support onload event on link elements - for example safari mac 5.1.7-- //in order to simulate load event on link elements use a known trick img = doc.createElement('img'); img.onerror = callBack; img.src = src; } }; callBack = function () { if (++counter === len) { SyntaxHighlighter.highlight(); window.SyntaxHighlighterLoading = false; } else { load(arr[counter], callBack); } }; load(arr[counter], callBack); } }());
[System.Web.Services.WebMethod] public static string TestMethod(string data) { return "Data received at " + DateTime.Now.ToString(); }now we can use the $.ajax method of jQuery to make calls to the page method we defined. Lets look how can we send a simple string:
// send a simple string var data2Send = '{"data":"this is a simple string"}'; $.ajax({ type: "POST", url: 'Default.aspx/Testmethod', data: data2Send, contentType: "application/json; charset=utf-8", dataType: "json", success: function (arg) { //call successfull }, error: function (xhr) { //error occurred } });
{"Message":"Invalid JSON primitive:","StackTrace":..."Second the parameter name of the Asp.Net Page Method must be same with the property name of json object we send to the server.
{"test":"this is a simple string"}json object to TestMethod we will receive the exception below :
{"Message":"Invalid web service call, missing value for parameter:data"}which states the page method was waiting for a json argument with a property named data but could not find one. On the other hand if we send a json object containing multiple property, Asp.Net will check the parameter to see if it contains a property with the same name as its parameter name. In our example it will search the object for a property name data. So if we send
{"test":"this is a simple string","data":"test"}our page method will pick the 'data' property and will not take other properties of the json object into consideration.
[System.Web.Services.WebMethod] public static string TestMethod(string data, string arg) { return "Data received at " + DateTime.Now.ToString(); }
// send an object with multiple parameters var data2Send = '{"data":"this is a simple string", "arg":"hello"}'; $.ajax({ type: "POST", url: 'Default.aspx/Testmethod', data: data2Send, contentType: "application/json; charset=utf-8", dataType: "json", success: function (arg) { //call successfull }, error: function (xhr) { //error occurred } });
var data = { name: 'Cem', surname: 'Karaca', birthDate: '05.04.1945', groups: [{ name: 'Kardaslar', Year: 1970, members: ['Unol Buyukgonenc', 'Seyhan Karabay', 'Huseyin Sultanoglu', 'Fehiman Ugurdemir'] }, { name: 'Dervisan', Year: 1974, members: ['Ugur Dikmen', 'Sefa Ulastir', 'Hami Barutcu'] }], links: ['http://en.wikipedia.org/wiki/Cem_Karaca', 'http://progressive.homestead.com/Cem_Karaca.html'] };
var data = { name: 'cem', surname: 'karaca' } //serialize object to json var jsonData = Sys.Serialization.JavaScriptSerializer.serialize(data); //deserialize json to javascript object var obj = Sys.Serialization.JavaScriptSerializer.deserialize(jsonData);
var data = { name: 'cem', surname: 'karaca' } //serialize object to json var jsonData = JSON.stringify(data); //deserialize json to javascript object var obj = JSON.parse(jsonData);
[System.Web.Services.WebMethod] public static string ComplexTypes(object data) { return "Data received at " + DateTime.Now.ToString(); }
// construct a complex object var complexObj = { name: 'Cem', surname: 'Karaca', birthDate: '05.04.1945', groups: [{ name: 'Kardaslar', Year: 1970, members: ['Unol Buyukgonenc', 'Seyhan Karabay', 'Huseyin Sultanoglu', 'Fehiman Ugurdemir'] }, { name: 'Dervisan', Year: 1974, members: ['Ugur Dikmen', 'Sefa Ulastir', 'Hami Barutcu'] }], links: ['http://en.wikipedia.org/wiki/Cem_Karaca', 'http://progressive.homestead.com/Cem_Karaca.html'] }; //our page method has a single parameter named 'data' //so we have to construct a json object with a 'data' property //and complexObj will be the value part //so our json object must be in form {"data":complexObj} //construct a new javascript object with a property named data //which contains the complexObj as value var obj = { data: complexObj }; var data2Send = JSON.stringify(obj);//convert obj to json //call the ComplexTypes page method with $.ajax({ type: "POST", url: 'Default.aspx/ComplexTypes', data: data2Send, contentType: "application/json; charset=utf-8", dataType: "json", success: function (arg) { //call successfull }, error: function (xhr) { //error occurred } });
var data = { name: 'Cem', surname: 'Karaca', birthDate: '05.04.1945', groups: [{ name: 'Kardaslar', Year: 1970, members: ['Unol Buyukgonenc', 'Seyhan Karabay', 'Huseyin Sultanoglu', 'Fehiman Ugurdemir'] }, { name: 'Dervisan', Year: 1974, members: ['Ugur Dikmen', 'Sefa Ulastir', 'Hami Barutcu'] }], links: ['http://en.wikipedia.org/wiki/Cem_Karaca', 'http://progressive.homestead.com/Cem_Karaca.html'] };
public class MyData { public class Group { public string Name { get; set; } public int Year { get; set; } public List<string> Members { get; set; } } public string Name { get; set; } public string SurName { get; set; } public string BirthDate { get; set; } public List<Group> Groups { get; set; } public string[] Links { get; set; } }
[System.Web.Services.WebMethod] public static string ComplexTypes(MyData data) { return "Data received at " + DateTime.Now.ToString(); }and here is the result :
//Send Complex Type1 as string to Json.Net //define and object that will be sent to server var simpleObj = { name: 'Cem', groups: ['Apaslar', 'Kardaslar'] }; //define a javascript object which has a property named data //the value of data property must be string //so we need to convert our obj data2Send = JSON.stringify({ data: JSON.stringify(simpleObj), type: 'type1' }); $.ajax({ type: "POST", url: 'Default.aspx/MultipleTypes', data: data2Send, contentType: "application/json; charset=utf-8", dataType: "json", success: function (arg) { //print the server response $result.html(arg.d); } });
[System.Web.Services.WebMethod] public static string MultipleTypes(string data, string type) { switch (type) { case "type1": { var type1 = new { name = String.Empty, groups = new List<string> {} }; var result = Newtonsoft.Json.JsonConvert. DeserializeAnonymousType(data, type1); } break; case "type2": { var type2 = new { text = String.Empty }; var result = Newtonsoft.Json.JsonConvert. DeserializeAnonymousType(data, type2); } break; } return "Data received at " + DateTime.Now.ToString(); }
[System.Web.Services.WebMethod] public static object ReturnComplexType() { return new { data = "Hello from server", time = DateTime.Now.ToString(), array = new string[]{"", "Yart", "Cem"} }; }
$.ajax({ type: "POST", url: 'Default.aspx/ReturnComplexType', data: {}, contentType: "application/json; charset=utf-8", dataType: "json", beforeSend: function () { $result.html("Sending Data..."); }, success: function (arg) { $result.html(arg.d); } });