Thursday, November 5, 2015

SharePoint Configuration Error (An exception of type Microsoft.SharePoint.Upgrade.SPUpgradeException was thrown. Failed to call GetTypes on assembly Microsoft.Office.InfoPath.Server )

I have been facing this error when running the SharePoint Configuration Wizard, and was able to find a solution after googling for some time.

This error occurs when Office 2013 is installed with SharePoint 2010 and when you try to Configure SharePoint Central Administration.

Error:

Failed to create the configuration database. An exception of type Microsoft.SharePoint.Upgrade.SPUpgradeException was thrown. Additional exception information: 
Failed to call GetTypes on assembly Microsoft.Office.InfoPath.Server, Version=14.0.0.0, Culture=neutral, 
PublicKeyToken=71e9bce111e9429c. Could not load file or assembly 'Microsoft.Office.InfoPath, Version=15.0.0.0, 
Culture=neutral, PublicKeyToken=71e9bce111e9429c' or one of its dependencies. The system cannot find the file specified.
 Could not load file or assembly 'Microsoft.Office.InfoPath, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' 
or one of its dependencies. The system cannot find the file specified. Could not load file or assembly 'Microsoft.Office.InfoPath, 
Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' or one of its dependencies. The system cannot find 
the file specified. Could not load file or assembly 'Microsoft.Office.InfoPath

The solution is to remove the below given folders from C:\Windows\assembly\GAC_MSIL (Check the "Important" section below)

1. Policy.14.0.Microsoft.Office.InfoPath
2. Policy.14.0.Microsoft.Office.InfoPath.Client.Internal.Host
3. Policy.14.0.Microsoft.Office.InfoPath.FormControl

Now re-run the Configuration Wizard!

Important:
You may not be able to access the this folder (C:\Windows\assembly\GAC_MSIL) directly. Check out my earlier blog post on how to access the GAC folder. Cheers!


Accessing the GAC folder structure using Windows Explorer

Many of us have accessed the Global Assembly Cache (GAC) for troubleshooting purposes. But when viewed using the Windows Explorer (C:\Windows\assembly), all the assemblies are rendered in a different way by the Operating System. This is not the actual physical structure of the GAC folder.


Try coping the same path and paste it on a browser (Chrome or Firefox) or access the path using command line, You might be surprised to see the real structure of the GAC folder. What you see in the Windows explorer is an aggregated view of the inner folders












To enable viewing the actual folder structure of the GAC from the windpows explorer, go to the Windows registry editor (regedit), create a string value key by the name "DisableCacheViewer" inside "HKEY_LOCAL_MACHINE\Software\Microsoft\Fusion" and set the value to "1". Now browse the same folder using windows explorer.


The earlier mentioned default nature of the GAC folder is achieved using the shell namespace extension. By using this, you can create custom functionality for windows explorer.



Sunday, November 9, 2014

Visual Studio Intellisense not Working (VS2012, VS2013)

The Intellisense feature in Visual Studio 2012 and 2013 do not seem to work well. It breaks down time to time and has almost become a big headache! So, what would be the easiest solution? to Google? Oh No!!!, thousands of options and answers and many of them don't really work! But if you are fine with deleting your Visual Studio settings without spoiling any of your code then this should be the easiest way for you!

1) In your start menu search "%AppData%" and enter. You will be taken to "Roaming" folder. (Make sure you have closed your Visual Studio Instance before start doing this.)

2) Go to "Microsoft > Visual Studio" inside the "Roaming" folder.

3) Here you will see the the visual studio versions installed in your machine as folder names.

4) If you are having intellisense issues with VS2012 then rename the "11.0" folder. For VS2013, "12.0" is the corresponding folder.

5) Now start a new Visual Studio instance and you are ready to go!

6) If everything works fine, just delete the renamed folder.

Happy Coding!!

Tuesday, January 14, 2014

Integrating WebEx Video Conferencing with ASP.NET - Creating a new WebEx Meeting


This article illustrates how to ingrate WebEx Web Conferencing solution into a .net application. WebEx is cool and powerful compared with the other video conferencing solutions I have worked with. We will be using the WebEx XML API in our demonstration.

The first thing you need to do is to sign up with the Cisco developer site.  After you get registered click on the "Try WebEx APIs" sub menu under "Develop and Test" menu. There you will find some information you need to access the API. You will be sending the Site URL,  Site ID, Partner ID as parameters on your request. XML Service URL is to where you will be sending your request to. Then you need to create a host account for you to schedule meetings.


Now you are ready to use your API! Let's create a web application in Visual Studio (Web Forms or MVC). I'm using a web forms application for rapid development. In this post we will only be covering about how to create a webex meeting.

The only thing you need to know when coding is how to create and send a web request and how to process an XML document.You don't need to know much! ;-). This is the request XML I will be passing to the WebEx XML Service (see above image for XML Service URL ).

  
yourhostemailaddress@live.com ******** 243585 g0webx! yourhostemailaddress@live.com
<!-- pass123 Test 4 Lushanthan myattendee@live.com true true true 900 20 42
-->
Please note that some of the tags have been commented as those features are not supported for a basic account. The 'MeetingType' tag is commented because we don't have an existing meeting template created. We can use 'MeetingType' if we already have templates created on our WebEx site with default set of attendees and in case if we want to use that. We have left out the 'confName' tag and the 'startDate' tag empty as we will be providing a UI for the user to enter those details and we will be binding them programmatically. We can also add more attendees if needed.

Below given code shows the "Create Meeting" button click event. Please note that we are getting the conference name and the attendee email list as user inputs from the form.

protected void Button1_Click(object sender, EventArgs e)
        {
            WebResponse response = null;
            Stream dataStream = null;

            try
            {
                string confName = txtMeetingName.Text;
                string attendeeList = txtAttendees.Text;

                //Get Emails separated by commas
                string[] emails = attendeeList.Split(',');

                //Create New Meeting and reload page                
                string strXMLServer = @"https://apidemoeu.webex.com/WBXService/XMLService";

                WebRequest request = WebRequest.Create(strXMLServer);
                // Set the Method property of the request to POST.
                request.Method = "POST";
                // Set the ContentType property of the WebRequest.
                request.ContentType = "application/x-www-form-urlencoded";

                XmlDocument xmlDocument = new XmlDocument();
                try
                {
                    XmlReader reader = new XmlTextReader(Server.MapPath("Xml/CreateMeeting.xml"));
                    xmlDocument.Load(reader);
                }
                catch (Exception)
                {
                    throw;
                }

                XmlNamespaceManager manager = new XmlNamespaceManager(xmlDocument.NameTable);
                manager.AddNamespace("serv", "http://www.webex.com/schemas/2002/06/service");

                //Set Meeting metadata
                xmlDocument.SelectSingleNode("/serv:message/body/bodyContent/metaData/confName", manager).InnerText = txtMeetingName.Text;
                xmlDocument.SelectSingleNode("/serv:message/body/bodyContent/schedule/startDate", manager).InnerText = DateTime.Now.ToString();

                //Set Attendees
                XmlNode attendeeListNode = xmlDocument.SelectSingleNode("/serv:message/body/bodyContent/participants/attendees", manager);

                if (attendeeListNode != null)
                {
                    foreach (string email in emails)
                    {
                        try
                        {
                            XmlNode attendeeNode = xmlDocument.CreateNode(XmlNodeType.Element, "attendee", "");
                            attendeeNode.InnerXml = "" + email.Split('@')[0] + "" + email.Trim() + "";
                            attendeeListNode.AppendChild(attendeeNode);
                        }
                        catch (Exception)
                        {
                            throw new Exception("Please insert valid email addresses");
                        }
                    }
                }
               
                byte[] byteArray = Encoding.UTF8.GetBytes(xmlDocument.OuterXml);

                // Set the ContentLength property of the WebRequest.
                request.ContentLength = byteArray.Length;

                // Get the request stream.
                dataStream = request.GetRequestStream();
                // Write the data to the request stream.
                dataStream.Write(byteArray, 0, byteArray.Length);
                // Close the Stream object.
                dataStream.Close();
                // Get the response.
                response = request.GetResponse();

                // Get the stream containing content returned by the server.
                dataStream = response.GetResponseStream();
                XmlDocument xmlReply = null;

                if (response.ContentType == "application/xml" || response.ContentType == "text/xml;charset=UTF-8")
                {
                    xmlReply = new XmlDocument();
                    xmlReply.Load(dataStream);
                }

                //Process Meeting Response
                string result = this.ProcessMeetingResponse(xmlReply);

                if (!string.IsNullOrEmpty(result))
                {
                    lblMessage.Text = result;
                }
            }
            catch (HttpException)
            {
                lblMessage.ForeColor = System.Drawing.Color.Red;
                lblMessage.Text = "An Http Exception occured. Please try again later.";
            }
            catch (XmlException)
            {
                lblMessage.ForeColor = System.Drawing.Color.Red;
                lblMessage.Text = "Xml Exception occured. Please try again later.";
            }
            catch (Exception ex)
            {
                lblMessage.ForeColor = System.Drawing.Color.Red;
                lblMessage.Text = ex.Message;
            }
            finally
            {
                if (dataStream != null)
                {
                    dataStream.Close();
                }
                if (response != null)
                {
                    response.Close();
                }
            }
            imgLoader.Style.Add("display", "none");
        }

Ok now! As you can see in line 86 in the code snippet ProcessMeetingResponse method needs to be implemented. Before implementing that method we need to know about the meeting reponse XML that we will be receiving from the WebEx XML Service for both the success case and the failure case. Here is a sample response we will be receiving on failure.

  
    
      FAILURE
      The user or site does not support this meeting type
      PRIMARY
      110002
    
  
  
    
  


And on success we will receive an XML with some more data.

  
    
      SUCCESS
      PRIMARY
    
  
  
    
      98691968
      
        
          https://www.webex.com/calendarurl1/j.php?ED=48591508&UID=BA24987F&ICS=MIFH&ST=12
        
        
          https://www.webex.com/calendarurl1/j.php?ED=48591508&UID=BA24987F&ICS=MIFA&ST=12
        
      
      f10324e2af4823c278fa1a6efadc426c
    
  


Note that in the success response we will get the meeting key and the icalender url which we can use to bind with our email calenders.

On ProcessMeetingRespons() method we return an empty string on success and a error reason on any exception.Error reason can be found inside the "serv:reason" tag in the failure XML.

Resources:
WebEx XML API Overview 
https://developer.cisco.com/site/tech/communication-collaboration/webex/webex-developer/develop-test/xml-api/reference/

WebEx XML API Reference Guide
https://developer.cisco.com/site/tech/communication-collaboration/webex/webex-developer/develop-test/xml-api/reference/

https://developer.cisco.com/fileMedia/download/1d70807a-6431-4a80-b13a-aa8faa4575b7

P.S: The sample mentioned in this article is done using the WebEx XML API. However, the same functionality can also be implemented using the WebEx URL API.


Sunday, August 25, 2013

நெஞ்சே எழு!


Tuesday, April 16, 2013

Returning a partial view on a MVC Ajax Form submit


In my previous post we talked about returning a Json object on a MVC Ajax form submit. There we had to write several Java-Script methods in order to process the response. In that case it was just about whether are registration (form1) was successful or not. But assume we need to show another form (form2) (without redirection), do some data filling there and submit it and that all these things have to be in Ajax.

One way you could achieve this, is to have both these forms in our html page and do a jquery show  and a hide on those forms. below given is the javascript code if are implementing this in our previous example.
function RegisterSuccess(data) {
    try {   
        if (data.Status == "0") {          
            $('#form1').hide();
            $('#form2').show();          
        } else {           
            $(".msg").addClass('error');
            $(".msg").html(data.Message);
        }
    } catch (e) {
    }
}

If we need to auto fill up some of the information in form2 from the database, we need to write javascript code to set the values for each of those fields. I remeber Scott Hanselman , saying "People who can read java-scripts are weird people!" (people who write too!) in one of this videos. So what if a js library writes all these javascripts for us and that we only need to return a view. Yes, Ajax.BeginForm takes care of all that. You just need to set the UpdateTargetId and the LoadingElementId parameters.

Ok now. Time for some coding! This is how are razor view look like.
@model AjaxMvc4.Models.RegisterModel
@{
    ViewBag.Title = "Register";
}

@ViewBag.Title.

Create a new account.

@using (Ajax.BeginForm("Register", "Account", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "formContent", LoadingElementId = "loader" })) { @Html.AntiForgeryToken() @Html.ValidationSummary()
Registration Form
  1. @Html.LabelFor(m => m.UserName) @Html.TextBoxFor(m => m.UserName)
  2. @Html.LabelFor(m => m.Password) @Html.PasswordFor(m => m.Password)
  3. @Html.LabelFor(m => m.ConfirmPassword) @Html.PasswordFor(m => m.ConfirmPassword)
}
@section Scripts { @Scripts.Render("~/bundles/jqueryval") }


In the controllers instead of returning a Json object we return a partial view. We can even pass a model and set if we need to fill some of the information in the new form (either from the database or from the previous model posted).



        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
                    WebSecurity.Login(model.UserName, model.Password);

                    UserModel user = new UserModel();
                    user.UserName = model.UserName;

                    return PartialView("_UserContactDetailsPartial", user);               
                }
                catch (MembershipCreateUserException e)
                {                   
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }
            return PartialView("_ErrorPartial");    
        }

User Details Partial View :
@model AjaxMvc4.Models.UserModel





@using (Ajax.BeginForm("Account", "ContactInformation", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "formContent", LoadingElementId = "loader" }))
{
    @Html.ValidationSummary(true)

    
Contact Details
User Name
@Html.DisplayFor(model => model.UserName) @Html.HiddenFor(model => model.UserName)
First Name
@Html.EditorFor(model => model.FirstName) @Html.ValidationMessageFor(model => model.FirstName)
Last Name
@Html.EditorFor(model => model.LastName) @Html.ValidationMessageFor(model => model.LastName)
Email Address
@Html.EditorFor(model => model.Email) @Html.ValidationMessageFor(model => model.Email)
Phone Number
@Html.EditorFor(model => model.PhoneNo) @Html.ValidationMessageFor(model => model.PhoneNo)
Mobile Number
@Html.EditorFor(model => model.Mobile) @Html.ValidationMessageFor(model => model.Mobile)
Address
@Html.EditorFor(model => model.Address) @Html.ValidationMessageFor(model => model.Address)

}
Don't forget to reference the jquery.validate.min.js and jquery.validate.unobtrusive.min.js for your ajax form to work!

Monday, April 15, 2013

Simple asp.net MVC Ajax Form Application

For this purpose, I'm using Microsoft asp.net MVC4 application.

Step1. As always, add a new project (Not an empty web project).







 Step2. Choose Internet Application from the project template.














Step3. As it is not an empty web project, there will be a set of code generated for you. For example the log in and the registration modules (Models, Controllers and Views). We are planning to alter them into Ajax forms.

Step4. Ok now, lets do some coding. We'll try to change the registration module. Go to register.cshtml in the Account folder inside the Views folder. Instead of the normal Html.BeginForm , change that to Ajax.BeginForm.

There are some slight changes you need to make when it comes to Ajax.BeginForm method.  You need to provide the HttpMethod and some Java-script functions as AjaxOptions other than controller and the action name. I have provided Java script methods for OnBegin, OnSuccess, OnComplete and OnFailure events. (Check Step 6 for JS implementaions)









































Step5. We also need to change the controller, since we are planning to return Json Objects so that we can process them in are Java scripts. I have made the return type as "JsonResult" instead of "ActionResult". ActionResult Class is parent class of JsonResult Class. However, I have opted for JsonResult so that I can be more specific (Register action will only return Jsons). Although, inside my "Register" action the registration process is the same, instead of doing a return View(), I do a return Json(). I need to process this Json at client side, according to the format I specify here. Here I'm simply returning a Status and a Message in my Json.


Step6. Now that we have written the code to send an ajax request and process it in the server side, we now need to handle the response in the client side. Below shown are my Java Script method implementations mentioned in step4. In my RegisterBegin() and RegisterComplete() methods I'm just showing and hiding a progress bar. RegisterFailure() method (called by OnFailure event) prompts for error with the HttpStatus Code. Note that this method gets fired only  for Http errors. Not for our application errors. We need to handle our application errors within the RegisterSuccess() method as they also get return with  http status success 200 (which triggers the OnSuccess event).

In our RegisterSuccess() method we differentiate the success registration and errors in registration based on the Status codes in our Json Object (Check Controller Code). If success, we are redirecting to the home page and if not we are showing the error message passed from the controller via the json object.



Step7. We are ready to launch now. Run the application and start registering. You will see a progress bar once you click on the submit button, and the success message on a successful registration. Try some exception scenarios as well! Good Luck!
























Saturday, July 28, 2012

Back to NLP!

guys,
I'm planning to do some work on Natural Language Processing work in the coming months. My last work on NLP was a Morphological Analyzer almost 2 years back! (A Tamil Morphological Analyzer and Generator) I think it's a good start for me to go on with what I love, and lets see what happens in the future!

I just thought of sharing today a presentation I did for my university mates in which I presented the paper "Arabic Morphology Using Only Finite State Operations" written by Mr. Kenneth R Beesley.Cheers!
 

Saturday, June 30, 2012

Lukka Chuppi...

Yesterday was a terrible day  for me guys! listening to "Lukka Chuppi" now (Of course, songs have been my mood-fixer). Enjoy! and this is my first post via blogger mobile. :-)

Saturday, April 28, 2012

Getting Started with Microsoft Entity Framework

I have been working with Microsoft Entity Framework for more than a year now. It's cool! Recently I got a chance to do a session to my office mates on "Getting started with Microsoft Entity Framework" at the weekly office tech talk presentations. I have uploaded them on slide-share. If it gets too much time too load visit either http://www.slideshare.net/slideshow/embed_code/12726298 or http://www.slideshare.net/lushanthan/getting-started-with-entity-framework

Friday, October 28, 2011

Cross domain policy for silverlight to access a WCF Service

Today, I'm posting about an issue which I faced when making a WCF Service to be accessible across different domains. And this was for a silver-light chat application. The chat application didn't work for me, and it threw me the below error when I debugged.
"An error occurred while trying to make a request to URI http://SampleSite/Chat Service.svc. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. This error may also be caused by using internal types in the web service proxy without using the InternalsVisibleToAttribute attribute. Please see the inner exception for more details."
After going through the MSDN, I was able to solve the issue.

"To enable a Silverlight control to access a service in another domain, the service must explicitly opt-in to allow cross-domain access. By opting-in, a service states that the operations it exposes can safely be invoked by a Silverlight control, without potentially damaging consequences to the data that the service stores.

Silverlight 4 supports two different mechanisms for services to opt-in to cross-domain access:

  • Place a clientaccesspolicy.xml file at the root of the domain where the service is hosted to configure the service to allow cross-domain access.

  • Place a valid crossdomain.xml file at the root of the domain where the service is hosted. The file must mark the entire domain public. Silverlight supports a subset of the crossdomain.xml schema. "
                                                                                                                      - MSDN [1]

This is even clear when you use the nikhilk's Web development helper with ie( can view request, response details) and check out the request [2] (check video) . It searches for those two files.

 
Here are the two files that are needed.
 
clientaccesspolicy.xml  

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="SOAPAction">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

crossdomain.xml

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-http-request-headers-from domain="*" headers="SOAPAction,Content-Type"/>
</cross-domain-policy>

Save both these files to the root of the domain where the service is hosted. If, for example, the service is hosted in http://fabrikam.com, then the file must be located at http://fabrikam.com/crossdomain.xml. Thanks to MSDN!


References

[1] http://msdn.microsoft.com/en-us/library/cc197955%28v=vs.95%29.aspx

[2]http://www.silverlight.net/learn/data-networking/introduction-to-data-and-networking/how-to-use-cross-domain-policy-files-with-silverlight

Check out the above video [2]  by Tim Heuer . It was really helpful!!!

Intellisense not working on MVC

Recently I had an opportunity to work on an Microsoft MVC 2 project. For me, the intellisense didn't work on the MVC web pages.

I also got the below run time error because of using the log4net dll. However, the reference to the dll was correct.

"ASP.NET runtime error: Could not load file or assembly 'log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821' or one of its dependencies. The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))".

Solution:

The Solution is to clear the "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\" files. It works now! Cheers!!!

Monday, January 17, 2011

onmouseover="JavaScript:this.style.cursor='hand'" not working in Firefox

hi all, this is a small CSS issue which I came across today, and was able to fix it out. This code below works wells with IE, but not with Firefox on mouse-over of an image/ div .

< div >
< asp:Image ID="Image1" runat="server" ImageUrl="~/Images/chat.png" onmouseover="JavaScript:this.style.cursor='hand' " / >
< /div >


The solution is to replace "hand" with "pointer".

< div >
< asp:Image ID="Image1" runat="server" ImageUrl="~/Images/chat.png" onmouseover="JavaScript:this.style.cursor='pointer' " / >
< /div >
cause, The standard is "pointer", not "hand". "hand" is for IE 4/5.

Regards,
Lushanthan. S

Sunday, October 31, 2010

More Stored Procedures (Add and Update)

Given below is a stored procedure for adding data into a table.
ex3-
create procedure MyStoredProcedure3
(
@para1 varchar(100),
@para2 int,
@para3 varchar(500)
)
insert into [Table1]
values (@para1,@para2,@para3)

note here that the parameters you input (@para 1,2 and 3) will set stored in the 1st, 2nd and 3rd columns respectively. And here you need to specify data for all the columns in the table. But, if you want to make it specific you can try the below example.

create procedure MyStoredProcedure3
(
@para1 varchar(100),
@para2 int,
@para3 varchar(500)
)
insert into [Table1]([column2],[column3],[column4]
values (@para1,@para2,@para3)

Here para1, 2 and 3 will get stored in the column 1, 2 and 3 of the table. The other columns in the table should allow nullable values, except for the primary key column which in this case can be auto-incremented. Also note that when you input data to an auto-incremented primary key column it will throw an exception.

Given below is a stored procedure for updating a row in a table.
ex4-

create procedure MyStoredProcedure4
(
@para1 int,
@para2 varchar(100),
@para3 varchar(500)
)
update [Table1]
set [column2]=@para2,[column3]=@para3
where [column1]=@para1

Good Day! See you next time with some more examples..

Saturday, April 25, 2009

Web Development and Design - Begining with SQL

Creating  Stored Procedures- Basics

 For this, you should have the basic knowledge on creating queries in SQL(visit http://www.w3schools.com/sql/default.asp).


Wat is really a stored procedure?

It is more like making the sql statements programmable! These stored procedures are stored in the database. It can take parameters and return what you want. Then you can easily call this procedure from a remote application, and get your result. It begins with the keyword create procedure


ex1-
Here is an example for the select query.
(If you want the whole records in the table)

create procedure MyStoredProcedure1
as
select from [TableName] 

ex2-
Here is an example for the select query with input parameters. (If  you want a particular row / set of row- using the where condition)
Here, the input parameter will be given by the user which is dynamic.But, when using a SQL statement we write the where clause like,
select * from [TableName] where [columnName] = 23. The value 23 should get changed according to what user inputs. For that we can write a procedure like ,
create procedure MyStoredProcedure2
(
/*input parameters with their type*/
@para1 varchar(50)
)
as
select * from [TableName] where [columnName] = @para1

Here the type of the parameter given should be the type of its corresponding [columnName].

In the next lesson we will look into more examples on stored procedures.
Good Day.