Wednesday, May 25, 2011

Jqgrid for MVC 2

Here i will put in code to demonstrate Jqgrid.This is one of the coolest grids available.There are many ways to implement this grid.There is a lot of documentation available for Jqgrid on its wiki,so i am not going to explain the stuff.The way i have implemented the grid is to have a search form and have ajax call made to the search controller and then let it return us a array data and that we feed directly to the grid.This grid will also have a double click event hooked up for all the rows returned.I have also used Block UI to block the page when we construct a dialog with all the information about the record.One problem i faced with Json is,the default max for JSon Serialization is very small,so i found a class LargeJSon on google which basically increases the default limit to
<jsonSerialization maxJsonLength="2147483644""></jsonSerialization>.

Here is the Main code

<script type="text/javascript" language="javascript">
$(document).ready(function() {


function Search() {
$(loading).show();
$.ajax({
type: "POST",
url: '<%=Url.Content("~/Search/Search")%>',
data: $("#SearchForm").serialize(),
datatype: 'json',
success: function(msg) {
if (msg != null) {
$("#Validation").hide();
var gridData = msg;
if (!loaded) {
loaded = LoadGridWithData(gridData);
}
else {
$("#list").GridUnload();
loaded = LoadGridWithData(gridData);
}
$(loading).hide();
}
},
error: function(xhr, status, error) {
var object = new Array();
object = xhr.responseText.split(';');
var response = '';
for (var i = 0; i < object.length; i++) {
var p = "<div>" + object[i] + "</div>";
response += p;
}
$("#Validation").html(response);
$("#Validation").show();
$(loading).hide();
}
});

}

var dialogOpen = false;

function LoadGridWithData(gridData) {
jQuery("#list").jqGrid({
sortable: true,
data: gridData,
datatype: 'local',
mtype: 'GET',
colNames: ['First Name', 'Middle Name', 'Last Name', 'Agent', 'State', 'Zip', 'Number', 'Type', 'Status', 'Date'],
colModel: [
{ name: 'FirstName', index: 'FirstName', width: 30, sorttype: 'text' },
{ name: 'MiddleName', index: 'MiddleName', width: 15, sorttype: 'text', align: 'left' },
{ name: 'LastName', index: 'LastName', width: 40, sorttype: 'text', align: 'left' },
{ name: 'Agent', index: 'Agent', width: 30, sorttype: 'int', align: 'left' },
{ name: 'State', index: 'State', width: 15, sorttype: 'text' },
{ name: 'Zip', index: 'Zip', width: 20, sorttype: 'int', align: 'left' },
{ name: 'Number', index: 'Number', width: 50, sorttype: 'int', align: 'left' },
{ name: 'Type', index: 'Type', width: 50, sorttype: 'text', align: 'left' },
{ name: 'Status', index: 'Status', width: 50, sorttype: 'text', align: 'left' },
{ name: 'Date', index: 'Date', width: 50, sorttype: 'date', resizable: false }
],
pager: '#pager',
rowNum: 20,
rowList: [5, 10, 20, 50],
gridview: true,
sortname: 'Number',
sortorder: "desc",
height: 400,
loadui: "enable",
loadtext: "Loading...",
autowidth: true,
rownumbers: true,
viewrecords: true,
caption: 'Quote Header Data',
ondblClickRow: function(id) {
$.blockUI({ message: "<h1>Retrieving Information. Please Wait...</h1>", timeout: 10000 });
var url = '<%= Url.Content("~/") %>' + "Search/Modal";
$.post(url, { Id: id }, function(response, status, xhr) {
if (status != "error") {
$.unblockUI();
$('#verificationedit-form').html(response).dialog("open");
}
else {
$.blockUI({ message: "<h1>Retrieving Failed.Please Try Again...</h1>" });
$('.blockOverlay').attr('title', 'Click to unblock').click($.unblockUI);
}
});
}
});
jQuery("#list").jqGrid('navGrid', '#pager', { del: false, add: false, edit: false, search: false });
return true;
}
}
</script>



<table id="list" cellpadding="0" cellspacing="0">
</table>
<div id="pager" style="text-align: center;">
</div>
<div id="verificationedit-form" title="Edit Verification Information">
</div>


//Controller


[HttpPost]
[EnableCompression]
public JsonResult Search(SearchModel searchModel)
{
LargeJsonResult result = new LargeJsonResult();

if (ModelState.IsValid)
{
List<GridModel> model = repository.Search(searchModel);
var jsonData =
(from pp in model
select new
{
id = pp.Id,
pp.FirstName,
pp.MiddleName,
pp.LastName,
pp.Agent,
pp.State,
pp.Zip,
pp.Number,
pp.Type,
pp.Status,
pp.Date
}).ToArray();

result.Data = jsonData;
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}
else
{
StringBuilder errorString = Utilities.BuildErrorMessageFromModelStateWithDelimiter(ModelState, ";");
Response.StatusCode = 500;
Response.Write(errorString.ToString());
return result;
}
}

Next time i will post the Jggrid code with inline editing.Happy Coding!!

Wednesday, January 26, 2011

autocomplete

autocomplete is one the coolest features for a UI to have.So i happened to get a chance to make it.I had some struggle initially as i am new to jquery but finally got it and it works like a charm.

To do this you need to download Jquery autocomplete bundle.So,all we need to do is when the document loads we need to do a ajax call to your action to get your results(which is coming from your database or file,etc).For me it is the database,so you want to play around with it to find a sweet spot where your UI is not getting a performance hit because your query is taking too long.

jQuery(document).ready(function() {
$.ajax({
type: "GET",
url: "controller/AutoComplete",
data: '{}',
success: function(msg) {
// Do something interesting here.
if (msg != null) {
data = msg.toString().split(",");
$("#Name").autocomplete(data);
}
},
error: function(xhr, status, error) {
// Boil the ASP.NET AJAX error down to JSON.
var err = eval("(" + xhr.responseText + ")");
// Display the specific error raised by the server
alert(err.Message);
}
});
}); 



Now in your action,you need to call your repository to return back results,here i am returning a comma seperated array which i spit it and feed to the the autocomplete script.


[HttpGet]
public ActionResult AutoComplete()
{
string model = repository.GetDistinctNames();
return Content(model);
}

That's it you see autocomplete feature in your UI and your clients will be happy.

Thursday, October 14, 2010

FileSystemWatcher Using Rx

This is a simple program which checks and reports for error files produced by ETL jobs.

namespace ErrorFileWatcher
{
public class ErrFileWatcher
{
private readonly FileSystemWatcher _fileSystemWatcher;
public IObservable ChangedFiles { get; set; }
public IObservable CreatedFiles { get; set; }
public IObservable DeletedFiles { get; set; }
public IObservable RenamedFiles { get; set; }
public IObservable Errors { get; set; }


public ErrFileWatcher(string directory, string filter, bool includeSubdirectories)
{
_fileSystemWatcher = new FileSystemWatcher(directory, filter)
{
EnableRaisingEvents = true,
IncludeSubdirectories = includeSubdirectories
};

ChangedFiles = Observable.FromEvent(
(EventHandler e) => new FileSystemEventHandler(e),
e => _fileSystemWatcher.Changed += e,
e => _fileSystemWatcher.Changed -= e).Select(x => x.EventArgs);

CreatedFiles = Observable.FromEvent(
(EventHandler e) => new FileSystemEventHandler(e),
e => _fileSystemWatcher.Created += e,
e => _fileSystemWatcher.Created -= e).Select(x => x.EventArgs);


DeletedFiles = Observable.FromEvent(
(EventHandler e) => new FileSystemEventHandler(e),
e => _fileSystemWatcher.Deleted += e,
e => _fileSystemWatcher.Deleted -= e).Select(x => x.EventArgs);


RenamedFiles = Observable.FromEvent(
(EventHandler e) => new RenamedEventHandler(e),
e => _fileSystemWatcher.Renamed += e,
e => _fileSystemWatcher.Renamed -= e).Select(x => x.EventArgs);



Errors = Observable.FromEvent(
(EventHandler e) => new ErrorEventHandler(e),
e => _fileSystemWatcher.Error += e,
e => _fileSystemWatcher.Error -= e).Select(x => x.EventArgs);


}

}
}


Windows Service code which calls the above class and also calls the sendemail method

try
{

while (true)
{
if (!RunToday)
{
if (IsItTimeToRun())
{
EventLog.WriteEntry("ErrorFileWactcher", "Watcher Started For " + DateTime.Now.Date, EventLogEntryType.Information);
SendEmails emails = new SendEmails();
Stopwatch sW = new Stopwatch();
sW.Start();
TextWriter writer = new StreamWriter(ConfigurationManager.AppSettings["FilePath"].ToString());
ErrFileWatcher fileWatch = new ErrFileWatcher(ConfigurationManager.AppSettings["FILEPATHTOBEMONITORED"], "*.txt", false);
fileWatch.CreatedFiles.Where(p => p.FullPath.Length > 0).Select(p => p.Name).Subscribe(p => writer.WriteLine(p.ToString() + " Created"));
fileWatch.ChangedFiles.Where(p => p.FullPath.Length > 0).Select(p => p.Name).Subscribe(p => writer.WriteLine(p.ToString() + " Changed"));
fileWatch.DeletedFiles.Where(p => p.FullPath.Length > 0).Select(p => p.Name).Subscribe(p => writer.WriteLine(p.ToString() + " Deleted"));
fileWatch.RenamedFiles.Where(p => p.FullPath.Length > 0).Select(p => p.Name).Subscribe(p => writer.WriteLine(p.ToString() + " Renamed"));
while (true)
{
if (sW.Elapsed.Minutes > 10)
{
sW.Stop();
writer.Flush();
writer.Dispose();
emails.SendEmail(true, ConfigurationManager.AppSettings["FilePath"].ToString(), "ERRORREPORT");
break;
}
}
}
else
{
Thread.Sleep(int.Parse(ConfigurationManager.AppSettings["SleepTime"]));
}
}
else
{
Thread.Sleep(int.Parse(ConfigurationManager.AppSettings["SleepTime"]));
}
}
}
catch (Exception ex)
{
EventLog.WriteEntry("ErrorFileWactcher", ex.Message, EventLogEntryType.Error);
}

Wednesday, August 25, 2010

Rx sample

In this post i have implemented a simple program which writes all the information of a customer class to a file.I took this example as it can be functional in a very short period of time.The code in this blog is inspired from Rx wiki.


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Threading;
using System.Concurrency;
using System.Diagnostics;

namespace ObservablePrototype
{
public class Prototype
{
string errorfile = ConfigurationManager.AppSettings["CustomerFile"];

public void RunProto()
{
Stopwatch sw = new Stopwatch();
sw.Start();

//Making Customer as observableCollection 
var customers = new ObservableCollection();

// adding event handler 
var customerChanges = Observable.FromEvent(
(EventHandler ev)
=> new NotifyCollectionChangedEventHandler(ev),
ev => customers.CollectionChanged += ev,
ev => customers.CollectionChanged -= ev);

//ling query for notify collection changed

var line = (from c in customerChanges
where c.EventArgs.Action == NotifyCollectionChangedAction.Add
from cu in c.EventArgs.NewItems.Cast().ToObservable()
select cu).BufferWithCount(10);

//using scheduler or u can just subscribe directly
Scheduler.ThreadPool.Schedule(() =>
{
line.Subscribe(cus =>
{
WriteCustomers(cus.ToList());
}
);
});

//start adding customers  
AddCustomers(customers);
WriteTimings(sw.Elapsed.Seconds + "Observable");
}

private void WriteTimings(string p)
{
TextWriter writer = new StreamWriter(errorfile, true);
writer.WriteLine(p);
writer.Close();
}



private void AddCustomers(ObservableCollection customers)
{
for (int i = 0; i < 50; i++)
            {
                Thread.Sleep(500);
                customers.Add(new Customer() { firstName = "K", lastName = "P" + i });
            }
            
        }



        public void StraightWrite()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            List customers = new List();
for (int i = 0; i < 50; i++)
            {
                Thread.Sleep(500);
                customers.Add(new Customer() { firstName = "K", lastName = "P" + i });
            }
            WriteCustomers(customers);
            WriteTimings(sw.Elapsed.Seconds + "Normal");
        }



        private void WriteCustomers(List customers)
{
foreach (var c in customers)
{
TextWriter writer = new StreamWriter(errorfile, true);
writer.WriteLine("FirstName : " + c.firstName + "  LastName : " + c.lastName);
writer.Close();
}
}

}
}






Wednesday, July 14, 2010

OTAClient + QC reporting with C#

When writing a Data Comparison tool, one of the requirements was to log the errors into Quality Center. Thats where OTAClient.dll comes into picture.
Open test Architecture is provided to access QC's database without using its GUI.
The code block below populates the bug object,posts it in QC's DB and also sends email to the concerned person.

public void GetDistinctRowsForQC()
{
DataContext dataContext = new DataContext();

var qc = (from details in dataContext.TableName
where details.RunId == _testRunID
select details);

QCReporting.LogErrorInQualityCenter(qc.Take(2));
}


internal static void LogErrorInQualityCenter(IQueryable qc)
{
TDConnectionClass QCConnection = new TDConnectionClass();
QCConnection.InitConnectionEx("http://qualitycenter/qcbin/");
QCConnection.Login("UserID", string.Empty);
QCConnection.Connect("C", "C");

BugFactory BFactory = (BugFactory)QCConnection.BugFactory;
Customization field = (Customization)QCConnection.Customization;
CustomizationFields f = (CustomizationFields)field.Fields;

List list = f.get_Fields("Bug");
Dictionary columnnames = new Dictionary();
foreach (CustomizationField fieldd in list)
{
if(!columnnames.ContainsKey(fieldd.UserLabel))
columnnames.Add(fieldd.UserLabel,fieldd.ColumnName);
}
int i = 0;
foreach(var q in qc)
{
IBug bug = (IBug)BFactory.AddItem(i);
bug.AutoPost = false;
bug.AssignedTo = "UserID";
bug.DetectedBy = Environment.UserName;
bug.Priority = "1-Low";
bug.Status = "New";
bug.Summary = q.ErrorMessage;
bug.Project = "CCC";
bug["BG_Reproducible"] = "Y";
bug["BG_Severity"] = "2-Medium";
bug[columnnames.Where(P => P.Key == "Issue Type").Select(p => p.Value).FirstOrDefault()] = "Defect";
bug[columnnames.Where(P => P.Key == "SDLC Phase").Select(p => p.Value).FirstOrDefault()] = "2-Project Execution";
bug[columnnames.Where(P => P.Key == "Detected on Date").Select(p => p.Value).FirstOrDefault()] = DateTime.Now;
bug[columnnames.Where(P => P.Key == "Application Group").Select(p => p.Value).FirstOrDefault()] = "Cu";
bug[columnnames.Where(P => P.Key == "Application Sub Group").Select(p => p.Value).FirstOrDefault()] = "CA";
bug[columnnames.Where(P => P.Key == "Project Number").Select(p => p.Value).FirstOrDefault()] = "C";
bug[columnnames.Where(P => P.Key == "Environment").Select(p => p.Value).FirstOrDefault()] = "QA";
bug[columnnames.Where(P => P.Key == "Detector Name").Select(p => p.Value).FirstOrDefault()] = new DirectoryEntry("WinNT://p/" + Environment.UserName + "").Name;
bug[columnnames.Where(P => P.Key == "Assigned Name").Select(p => p.Value).FirstOrDefault()] = new DirectoryEntry("WinNT://p/" + Environment.UserName + "").Name;
bug[columnnames.Where(P => P.Key == "Verified By").Select(p => p.Value).FirstOrDefault()] = "UserID";
bug[columnnames.Where(P => P.Key == "Verifier Name").Select(p => p.Value).FirstOrDefault()] = new DirectoryEntry("WinNT://p/" + Environment.UserName + "").Name;
bug[columnnames.Where(P => P.Key == "ReopenCountField").Select(p => p.Value).FirstOrDefault()] = "0";
bug[columnnames.Where(P => P.Key == "Source").Select(p => p.Value).FirstOrDefault()] = "Test";
bug[columnnames.Where(P => P.Key == "Reopen Count").Select(p => p.Value).FirstOrDefault()] = "0";
bug.Post();

bug.Mail("UserID", "UserID", 4, "New Defect Notification", q.ErrorMessage);
i++;
}
QCConnection.DisconnectProject();
QCConnection.Logout();
}