Search This Blog


Saturday, November 21, 2015

Crystal Report not getting displayed (with Error: bobj is undefined)

Few days back, I encountered a problem with Crystal Reports while hosted in IIS, it was not getting displayed at-all on ASP.Net page. After searching I got fixed with this, here are the 2 steps you might need to follow in case you face the same problem.
  1. Copy aspnet_client\system_web\4_0_30319\crystalreportviewers13 folder to you website's root directory. This would fix the problem in some cases. If not, try also the second point.
  2. There is already defined a section tag <sectionGroup name="crystalReports"> in web.config, here we need to add one more tag for crystal report viewer aso follows:
    <section name="crystalReportViewer" type="System.Configuration.NameValueSectionHandler" />
    Put the above line just below the <sectionGroup name="crystalReports"> line, before the closing </sectionGroup> tag.

    Somewhere in the last part of web.config, you will find a rptBuildProvider tag like this:
       <add embedRptInResource="true" />
    Just below  this tag, you have to add new tag for crystal report viewer to define the path from where it could find its required files.
       <add key="ResourceUri" value="/crystalreportviewers13" />
    Here we have defined the path as we have put the crystalreportviewers13 directory in the root of our website. Also you can place it some where else (i.e. in nested directories) if you want, so you have to change the path accordingly in ResourceUri key-value.
Now you can view your crystal report.

Monday, November 9, 2015

AngularJS - Form Validation

In this article I will explain how to validate web forms using AngularJS. It provides an easy way to validate data on client side and prevents sending post back to server until we receive correct data according to the defined rules. We can't depend on client side validation to keep our web applications secure, but it provides instant feedback to the user and enhance user experience making our form more interactive.

Validation Directives and Properties

We need to place fields within the form tag and give a name to it. Also, it's important to assign a name to each input field. AngularJS has many directives to provide form validation, following are the available on a classic input field.
Directive Type Description
ng-required boolean Sets the required attribute if set to true
ng-minlength number Sets the minlength validation error key if the value is shorter than minlength.
ng-maxlength number Sets the maxlength validation error key if the value is longer than maxlength.
ng-pattern string Sets pattern validation error key if the ng-model value does not match the regExp in the attribute value.
We can achieve some of these validations through HTML5, but the advantage of using AngularJS directive is that it allows to maintain two-way data binding between model and view.
AngularJS added some properties to form that helps us to validate and provides various information about the current state of input controls and the form. These are:
Boolean: $valid, $invalid, $pristine, $dirty
Object: $error (could be as: { required: false, email:true })
The result can be evaluated through the boolean property $valid. It will be updated based on the validation rules defined for each field by particular directives. If any of these violates the validation rule(s), the result will be false.
The $pristine value by default start with true and becomes false after receiving any input value.
The $dirty flag is just the opposite, it starts with false and becomes true after the first input value is received.

Code Review

We will use a sample demo form to see how validation works in AngularJS. You will see the code listing in Test.html page. I have added the following libraries in head tag for AngularJS and Bootstrap:
<link href="client/assets/css/bootstrap.min.css" rel="stylesheet"></link>
<script src="client/assets/libs/angular.js"></script>
Define ng-app and ng-controller in body tag, to make html page aware of angular framework.
<body ng-app="validationDemoApp" ng-controller="myController">
    <form name="myForm" ng-submit="submitForm(myForm.$valid)" novalidate class="form-horizontal">  
Body tag is using ng-app attribute to our angular application module 'validationDemoApp' and binded to the controller 'myController'. We have placed novalidate attribute to our form tag, it will prevents the HTML5 validation, because we will be validating ourselves. And on submit form, we are calling our javascript function submitForm(myForm.$valid) which accepts a boolean variable passed by form property $valid, within this function we can check this boolean to see if our form data is validated or not according to our defined rules.
Here is the html content for name field:
<div class="form-group">
 <label class="control-label col-sm-2" for="name">Name:</label>
 <div class="col-sm-6">
  <input type="text" name="name" placeholder="Name" class="col-lg-6" ng-model="" 
      required ng-minlength="3" ng-maxlength="10" ng-pattern="/^[a-zA-Z0-9]*$/">
  <span ng-show="$error.required && isSubmitted" class="help-inline col-lg-offset-1">Please enter name.</span>
  <span ng-show="$error.minlength" class="help-inline col-lg-offset-1">Minimum length should be 3.</span>
  <span ng-show="$error.maxlength" class="help-inline col-lg-offset-1">Maximum length should be 10.</span>
  <span ng-show="$error.pattern" class="help-inline col-lg-offset-1">Please enter only alphanumeric characters.</span>
I have placed each form's field inside a div which has defined the conditional css class as ng-class="{ 'has-error' :$invalid && isSubmitted }", it means apply the css class 'has-error' only if the 'name' property of 'myForm' is 'invalid' and also 'isSubmitted' flag is true. '$invalid' is the forms default property, while 'isSubmitted' is our local variable added to the $scope inside the submit function.
At initial state, you will get the form similar to this with no validation messages:

 Next for the name field, we have defined 3 validation rules as required ng-minlength="3" ng-maxlength="10" which are self-explanatory. ng-pattern="/^[a-zA-Z0-9]*$/" will validate name field to accept only alphanumeric characters. Right after input tag I have placed <span> tags to display error messages with ng-show attribute to show/hide based on validation state.
At first it will display the validation message on screen if 'required' becomes true and also if user try to submit the form. Similarly we can set-up all other fields with different validation rules and different error message defined in <span> tags.
When you click on submit button without making any changes you will see the required validator messages like this:
 For Age field, I put the range validation in range 20-40, and for this I have used custom validator(custom angular directive). So if you enter anything outside this range you will get error message like this:
 I have added an attribute named 'age-validate', this is not AngularJS default attribute, it is custom defined attribute contains our logic to validate age field. Lets move on to JavaScript code:
   // create angular app module
        var validationApp = angular.module('validationDemoApp', []);

        // create controller
        validationApp.controller('myController', function ($scope) {

            // all validation has passed
            //parameter is passed in form tag on submit, i.e. myForm.$valid
            $scope.submitForm = function (isValid) {
                $scope.isSubmitted = true;

                // check the form is valid
                if (isValid) {
×Success! Your form is submitted successfully.
'); } }; }); validationApp.directive('ageValidate', function () { return { require: 'ngModel', link: function (scope, elem, attr, ngModel) { ngModel.$parsers.unshift(function (value) { if (value >= 20 && value <= 40) { ngModel.$setValidity('ageValidate', true); } else { ngModel.$setValidity('ageValidate', false); } return value; }); } }; });
First we created application module 'validationApp', then added our controller 'myController'. Inside myController we have defined our 'submitForm' function which will be called when the form submitted successfully after passing all validations.
Then comes the custom validation part (or custom angular directive). Note that for custom directive name 'ageValidate' is define will cameCase. Inside the 'link' function, we actually defined our validation logic. Here I am checking if value is between 20-40 then it is valid age otherwise 'false' will be set-up as being invalidated. ngModel.$setValidity('ageValidate', true) is the ultimate function where you can set the validity falg (true or false) providing the custom directive name.
Note: Keep remember that when we are defining custom directive, we are using camelCase without any dashes or underscores, but when we put this directive in html tags, we have to put dashes(-) in between words like in this example, I placed 'age-validate' attribute to the input tag for 'Age'.
We learned how to validate various types of inputs in AngularJS with built-in directives, as well as how to define our own custom validation rule in Angular way. I hope you enjoyed this article and got something out of it. I appreciate your feedback/comments or any improvements you want to suggest in this topic, to help in making the article better and helpful for others.

Thursday, October 29, 2015

AngularJS - How to GET and POST data by http methods Get / Post

In this post, we will see how to use http requests in AngularJS. For the scope of this post, I assumed that we have already developed ASP.NET WebAPI, say for Products. So we have a ProductController which have action methods for CRUD operations. Lets see how we call that methods from AngularJS, I am using AngularJS factory method as a service componenet to communicate with server.

For example the following code snippet assumes you have a app module varaible defineds as demoApp, here we are creating a productFactory with a dependency parameter $http which we use to make requests to server.
demoApp.factory('productFactory', function ($http) {
This is how we create a get request over $http object, we passed a URL to ProductController and calling its Get method, which will return data in json string. We also passed 2 callback functions as parameters, first one is called if the request is succesfull and the second will be called if request encountered any error.
 success(function (data, status, headers, config) {
  // successfully get json response from server
  console.log("get products list - success");
 error(function (data, status, headers, config) {
  // log error
This is how we can create a post request over $http object. First define an object, say config, which will define the request headers or other configuration properties. Here we are passing three parameters to the Post function, first is the URL with Controller's post action method, second is the object we want to pass as parameter/data to that function, third is our configuration object we want to set with this request.
  var config = {
  headers: { 'Content-Type': 'application/json' }

$'api/Product/PostProduct', product, config)
  function (response, status, headers, config) {
     //sucessfully posted to server
     console.log('PostProduct success: ' + product.Id);
  function (response, status, headers, config) {         
     //log error
     console.log('PostProduct failed.', response, status, headers);
Similarly following code segment will make a delete http request. Here we are only passing productID as query string parameter to the required URL, i.e. Controller's delete action method will accept an integer variable productID as parameter.
  var params = "productID=" + id;
$http.delete('api/Product/DeleteProduct?' + params)
  function (response, status, headers) {
   //sucessfully processed delete request
   console.log('DeleteProduct success: ');
  function (response, status, headers) {
   //log error
   console.log('DeleteProduct failed.', response, status, headers);
Hope this post helps you, give an idea how to deal with http methods in AngularJS.

Saturday, October 24, 2015

No type was found that matches the controller named 'values'.

I created a new project for, added a default controller named ValuesController1. When I tried to run and call the controllers action methods I got this error:
No type was found that matches the controller named 'values'.

Even after a whole day spent on googling, I could not find any solution. There are so many post/suggestions to solve this error but no one worked for me. Then I just
tried simply to change the controller's name and it works amazingly.

When a new controller is added, it was like this:
  ValuesController1 : ApiController

I just simply removed "1" from the controller's name, and make it:

  ValuesController : ApiController

And it works in my case.

Monday, October 12, 2015

MS SQL Server - Find physical folder path for data files using master.dbo.xp_regread

In previous post, we found a way to get the location path to store database files for SQL Server. Another way to find the physical path is master.dbo.xp_regread or master.dbo.xp_instance_regread. You can use these procedures to find the physical path where MS SQL Server stores database files.

xp_regread reads the exact literal registry path you specify, while xp_instance_regread reads(or can transform) the path you specify so that it matches the instance of SQL Server that you're currently using.

Lets see an example:
declare @MasterMdfFile1 nvarchar(512)
exec master.dbo.xp_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\Parameters', N'SqlArg0', @MasterMdfFile1 output

select @MasterMdfFile1 = substring(@MasterMdfFile1, 3, 255) --removes extra '-d' in-front of path

declare @MasterMdfFile2 nvarchar(512)
exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\Parameters', N'SqlArg0', @MasterMdfFile2 output

select @MasterMdfFile2 = substring(@MasterMdfFile2, 3, 255) --removes extra '-d' in-front of path
select @MasterMdfFile1 as MasterMdfFile1, @MasterMdfFile2 as MasterMdfFile2
Sample Output:
MasterMdfFile1    MasterMdfFile2
NULL                             C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL2008R2SP2\MSSQL\DATA\master.mdf

Here we see that master.dbo.xp_regread returns NULL to @MasterMdfFile1 variable, because it could not find the literal registry path we provided. But master.dbo.xp_instance_regread is showing the result because it converts the path that matches the current instance of SQL Server we are using.