12/31/09

Validation

Now, since the user can write free text in the txtBirthDate input we need to validate if the date he intered is in the correct format.
To do so i will use the RegulaExpressionValidator.
lets write some regular expression to validate that date is in the dd.MM.yyy format...
^(((0[1-9]|[12]\d|3[01])\.(0[13578]|1[02])\.((1[6-9]|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\.(0[13456789]|1[012])\.((1[6-9]|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\.02\.((1[6-9]|[2-9]\d)\d{2}))|(29\.02\.((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$


Oops! A little problem here: the validator functions are triggered by "onChange" event causing a bug


Frotunately there is a solution- The plugin have its own validator:

We have only to add two more js files:



<script src="/moia/jquery.datepick.package-3.5.2/jquery.validate.js" type="text/javascript"></script>
<script src="/moia/jquery.datepick.package-3.5.2/jquery.datepick-validation.js" type="text/javascript"></script>




{The order is important!}
and add to our code:





   23   $('#form1').validate({
   24   errorPlacement: $.datepick.errorPlacement,
   25   rules: {
   26       txtBirthDate: { dpMaxDate: [] }
   27   },
   28   messages: {
   29     txtBirthDate: '<span style="color:red"></span>'
   30   }
   31
   32   });


Now we almost got the thing working , only one imporatne thing left:
there must be the "name" attribute inside txtBirthDate control. (The name is not compatible tag for asp control so you will get warning)


<asp:TextBox ID="txtBirthDate" runat="server" Height="24px"  name="txtBirthDate">






Now the datepicker and validator should work.
Good

12/23/09

The ASP.NET project


Now we arte at the step of ASP.NET. Open the Visual Studio, New , WebSite.
Usualy there is already Default.aspx webpage in the site root folder.
I have added the txtVisa and  txtBirthDate textboxes to the page

Now lets drag the jquery.datepick.package-3.5.2 -  the folder containing the JqueryDatePicker Plugin, to the root  directory.


Now lets write the code that applying the datepicker on the txtBirthDate textbox:



 <script src="jquery.datepick.package-3.5.2/jquery.datepick-ru.js" type="text/javascript"></script>
 <script src="jquery.datepick.package-3.5.2/jquery.validate.js" type="text/javascript"></script>
 <script src="jquery.datepick.package-3.5.2/jquery.datepick-validation.pack.js" type="text/javascript"></script>
 <script type="text/javascript">


<script type="text/javascript">
$(function() {
    $('#txtBirthDate').datepick();

});
</script>






Adding smoothness.datepick.css to App_Themes>Theme1 folder, for styling the plugin and
adding the jquery.datepick-ru.js for russian localization, and here we are:







How to set range ?

Well now the control came alive and this is the time to do some modifications:
Firstly  we dont want the user to choose the date late than today aren't  we?
So this code will make it up for us:

$(function() {$('#txtBirthDate').datepick({maxDate: 0},yearRange:('-30:+0'));
});

The code yearRange:('-30:+0') is for make the dropdown years to be 30 years earlier than today

What is jquery?

Jquery its great invention in the world of javascript. Its an opensource js library that make you able to easily access all the dom elements and make many intreresting effects and manipulatiuons on HTML tags.  You can read about it in their site.
We need now to go to "Plugins" section and download the DatePicker plugin we want to implement. You can download it also from here:
http://plugins.jquery.com/project/datepick
There is sample datepickBasics.html  page in the package, but you have first to download the jquery library itsef to see the plugin in action. (You can download the newest version from the main page :http://jquery.com/)

Now you get it huh?
Note that all the plugin is pure javascript, no dlls, no server language...Isn't it grate thing?

Jquery Datepicker in ASP.net control

In this small project i want to do one simple thing:
To implement Jquery Datepicker on ASP.NET page.

My additional requirements are:
The datepicker must be attached to enabled free text insert textbox,
with russian localization and validator that validates the date format - dd.MM.yyy (for example : 31.12.2009)


Its sounds very simple and so it is - who said i must write in my blog only about  very complicate things?
So lets do it....

10/30/09

Build new question Page



In this page the Admin will be able to add a new question to existing survey.  This was very complicated task for me to build this page...
I wil explain:
Those are the controls i used on the page:





The left upper control is for displaying all the options [answers] of a certain question.
The control [form] beneath is for add another option to options list.
The control at the right is for inserting the question type and text. The "insert" button of this form makes all question data [the text, type and options] being submitted to storing engine.

DOWNLOAD SOURCE

10/25/09

The application is online now!

Now you can view  and use the apllication at this URL.
everybody can play with it -create survey, edit survey and its questions, answer and view surveys

Admin

username:admin
password%6437355

10/21/09

Deploying website to remote server

Now i need to deploy all the site to remote hosting, with all pages and all database structure.
Also i want to make some users and roles so the site can be usable.
How to do it without copying the data from local to remote the database?
There is the way:
ASP.NET Config Tool


You can set the users roles and setting on remote site with ASP.NET Config Tool.
Note:When  you want ASP.NET Config Tool to work on not default aspntedb.mdf databse
you need to configure it first - How to do it? you can read this article that explains simple and clearly all about this tool.

To doing this you need only to change the connection string of providers (Rolemanager and Membership Customuized providers in web.config )

<connectionStrings>
   
 <add name="MyConnectionString"
    connectionString="Data Source=my_server;Initial   Catalog=my_DB;User my_user;Password=my_passwd;Integrated Security=False;"
     providerName="System.Data.SqlClient" />
</connectionStrings>

<roleManager enabled="true" defaultProvider="CustomizedRoleProvider">
       <providers>
          <add connectionStringName="MyConnectionString"
             name="CustomizedRoleProvider"
             type="System.Web.Security.SqlRoleProvider"
             applicationName="/M-survey1" 
             />
       </providers>
</roleManager>
<membership defaultProvider="CustomizedMembershipProvider" >
       <providers>
        
         <add connectionStringName="MyConnectionString"
               name="CustomizedMembershipProvider"
               requiresQuestionAndAnswer="false"
               type="System.Web.Security.SqlMembershipProvider"
               applicationName="/M-survey1"
              />
        
</providers>

Important!

After congifuring the users and members of the application
I found that the exisitnig usrs cannot logion and new registered users cannot access the role restricted areas.
after investigation I found that
the reason to this behavior was Appliction Name field somehow had different values for newly registered and for registered with aspNetConfiguration Tool users.


10/9/09

View Answerers Button



This button must show the list of users who answered the survey. Which survey? The one with its checkbox checked, of course :
This code is for finding which survey is checked (selected)
    private int findCheckedSurvey()
    {
        int survId = -1;
        foreach (RepeaterItem ri in Repeater1.Items)
        {
            CheckBox chkBox = (CheckBox)ri.FindControl("CheckBox1");
            if (chkBox != null && chkBox.Checked)
            {
                HiddenField hf;
                hf = (HiddenField)ri.FindControl("surveyID");
                survId = Convert.ToInt32(hf.Value);
                return survId;
            }
        }
        return survId;

    }


It means that only one survey allowed to be checked at once. How to force user not to check
more than one?
I wrote this code that unchecks the other checkboxes once user checked one of the surveys:
    protected void unCheckOthers(object sender, EventArgs e)
    {
        foreach (RepeaterItem ri in Repeater1.Items)
        {
            CheckBox chkBox = (CheckBox)ri.FindControl("CheckBox1");
            CheckBox c = (CheckBox)sender;
            bool thisIs=false;
            if (c.NamingContainer == chkBox.NamingContainer)
            {
                thisIs = true;
            }
   
           
            if (chkBox != null && chkBox.Checked && !thisIs)
            {
                chkBox.Checked = false;
            }
        }
    }

Note, that all the checkBoxes have the same ID property, so if we want the newly checked checkbox to stay checked we must use NamingContainer property which gets the unic identifier of repeater tags.
Important:If you want your checkboxes CheckedChacnged event to be handled at server code - you must set IsPostBack property to TRUE 

9/29/09

Validation of Publish button

I want that publish/unpublish command will be performed only if the survey have at least one question.
If the publish button pressed in the zero -question line - the user must get the red warning message:

You cannot publish survey with zero questions


But how to do it? The validate function cannot receive any additional parameters except
object sender, ServerValidateEventArgs e
And we cant even figure out which repeater item sended the command since the publish button not requires any item checkboxses to be checked.

Custom validator:

<asp:CustomValidator ID="CustomValidator2" runat="server"
ErrorMessage="You cannot publish survey with zero questions"
ValidationGroup="zeroQuestions" Display="Dynamic" OnServerValidate="IsZeroQuestions">
</asp:CustomValidator>

It raises the server-validation function IsZeroQuestions
how can this function "know" what the questions number of line(Repeater Item) whose raised it?



Well, it means i need to change the way the Publish/Unpublish button working:
From now it will work this way:
protected void PublishThisSurvey(object sender, RepeaterCommandEventArgs e)
    {
        RepeaterItem ri = Repeater1.Items[e.Item.ItemIndex];
        CheckBox chkBox = (CheckBox)ri.FindControl("CheckBox1");
        chkBox.Checked = true

        Validate("zeroQuestions");

        if (!Page.IsValid)
        {
        CustomValidator2.ErrorMessage = "Cannot publish this
            survey with zero questions";


            chkBox.Checked = false;
            return;

        }


        HiddenField hf;
        hf = (HiddenField)ri.FindControl("surveyID");
        int surveyID = Convert.ToInt32(hf.Value);

HiddenField isPhf = (HiddenField)ri.FindControl("IsPublished_hf");
        bool bIsPublished = Convert.ToBoolean(isPhf.Value);
      

        //turn upside
        bIsPublished = (bIsPublished) ? false : true;
        clsDataAccess myclass = new clsDataAccess();
        myclass.UpdateSurveyPublished(surveyID, bIsPublished);
        Repeater1.DataBind();
    }



and the trigger will be ItemCommand of Repeater:
<asp:Repeater ID="Repeater1" runat="server"
DataSourceID="SurveysSqlDataSource" OnItemCommand="PublishThisSurvey">                                    

9/28/09

To make publish/upublish buttons



The surveys list is displayed by using the Repeater control:

<asp:Repeater ID="Repeater1" runat="server"
DataSourceID="SurveysSqlDataSource" >
          
<HeaderTemplate>
<table class='adminlist' cellspacing='1'>
<thead>
<tr>
<th style="width:5px">
Id</th>
<th>
Survey</th>
<th>
Description</th>
<th style="width:5px">
Questions</th> 
<th style="width:5px">
  Answerers
</th>                                                                                     
<th style="width:5px">
Published
</th>
 </tr>
</thead>
</HeaderTemplate>
<ItemTemplate>
<tr>
  <td>
<asp:HiddenField ID="surveyID" Value='<%# Eval("survey_id")%>' runat="server" />
<asp:CheckBox ID="CheckBox1" runat="server"  OnCheckedChanged="unCheckOthers"  AutoPostBack="True"/>
<td>
<%# Eval("name")%></td>
<td>
<%# Eval("description")%></td>
  <td align="center">                                   
<%# Eval("QuestionNum")%>                                       
</td>  
<td align="center">                                   
  <%# Eval("answerersNUM")%>                                       
</td>                                     
<td align="center">
                                       
<asp:ImageButton ID="IsPublishedImageButton" runat="server" ImageUrl='<%#setImageButtonImg( Eval( "IsPublished"))%>'  CommandName='<%# setCommandIsPublished( Eval( "IsPublished"))%>'  CommandArgument='<%# Eval("survey_id") %>' OnCommand='PublishThisSurvey' Enabled='<%# IsEnabled(Eval("QuestionNum")) %>'/>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>

To make the publish \ unpublish button i used imageButton control. When  you click it -the survey become published (or unpublished-depends on its status before)


<asp:ImageButton ID="IsPublishedImageButton" runat="server" ImageUrl='<%#setImageButtonImg( Eval( "IsPublished"))%>'  CommandName='<%# setCommandIsPublished( Eval( "IsPublished"))%>'  CommandArgument='<%# Eval("survey_id") %>' OnCommand='PublishThisSurvey' Enabled='<%# IsEnabled(Eval("QuestionNum")) %>'/>


It was hard work
Because i tried to found a way to pass 2 parameters  to PublishThisSurvey
function: 1-the current state(Published or not) and 2-survey Id.

And it very strange but somehow there is only one command argument avaliable . So finally i find out that i can use the "Command name" property for second argument.
May be it is a very clumsy solution...




    protected void PublishThisSurvey(object sender, CommandEventArgs e)
    {
    

        int surveyID = Convert.ToInt32(e.CommandArgument);
        int IsPublished = Convert.ToInt32(e.CommandName);
        bool bIsPublished = Convert.ToBoolean(IsPublished);

        //turn upside
        bIsPublished = (bIsPublished) ? false : true;
        clsDataAccess myclass = new clsDataAccess();
        myclass.UpdateSurveyPublished(surveyID, bIsPublished);
        Repeater1.DataBind();
    }

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...