Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a C# Method in a VisualWebPart (.cs) from different Class within same Namespace

Tags:

c#

sharepoint

I am very new to C# and Sharepoint Programming.

I am trying to learn about WebPart and C# used on it. I made a visual webpart which adds/deletes Items on a list. I have a Method which is called on a Button click which add Item in the List.

Here is my Method:

public void TestMethod()
{
    using (SPSite oSPSite = SPContext.Current.Site)
    {
        using (SPWeb ospweb = oSPSite.OpenWeb())
        {
            SPList lst = ospweb.Lists["CusomList1"];

            SPListItem item = lst.Items.Add();

            item["Item1"] = txt1.Text;
            item["Item2"] = txt3.Text;
            item["Item3"] = Convert.ToInt32(txt3.Text);
            item["Item4"] = txt4.Text;
            item.Update();
        }
    }            
}

This is called as:

protected void Button1_Click(object sender, EventArgs e)
{
    TestMethod();
}

This works Fine. I am trying to use the same method on a second WebPart which does the same thing (add item).

However when I added a new Visual Webpart on the same project and called the class and method as

protected void Button1_Click(object sender, EventArgs e)
{
    VWP1 NewClass = new VWP1();
    NewClass.TestMethod();
}

This Add button does not work and when I do a debug I get the following message:

Object reference not set to an instance of an object.

Can someone please tell me what should I do?

like image 754
Andres Morales Avatar asked Nov 12 '22 17:11

Andres Morales


1 Answers

What you need to do is separate out the logic of saving the item in the list from the logic of interacting with the user interface.

Make a separate function that takes the data to be saved and saves it:

public static void SaveItem(string item1, string item2, int item3, string item4)//TODO rename parameters
{
    SPListItem newItem = SPContext.Current.Web.Lists["CusomList1"].AddItem();
    //set fields of new item
    newItem.Update();
}

Then you can put that method in a utility class somewhere.

After you've done that you can call the method from each of the webparts:

protected void Button1_Click(object sender, EventArgs e)
{
    MyUtilityClass.SaveItem(txt1.Text, txt2.Text, Convert.ToInt32(txt3.Text), txt4.Text);
}

As for why, there are a number of things going on here. The main problem is that when you create a new instance of the first visual webpart and call the method it's not accessing the textbox values of your second webpart, it's accessing the textbox values of the newly created webpart; the one that hasn't ever been shown the the user, or initialized by ASP. Because ASP (or you) never called it's initialization functions the textbox field were all null, hence your error. If you did initialize it then they'd all have empty text values, and it still wouldn't help you. The interaction with textboxes needs to happen within each of the different webparts; you can't (or at the very least shouldn't; it would be bad practice to allow it) access the internal controls from another class. What you can move to another class is everything besides the actual UI interaction; in this case the saving of the item to a list.

Several side notes:

  • You put the current context's SPSite in a using block; that will dispose of it. Don't do that. Only dispose of Site/Web objects that you create. The current context's site/web objects are re-used for different request; if you dispose of it that request will work, but when the disposed object is passed to the next request it will break, and it results in often hard to debug errors as the problem is in another request entirely.
  • You open up a new web in that example; are you sure that the current context's web isn't appropriate? If it's not, and you really do want the root web and won't always be at the root web, you can use SPContext.Current.Web.RootWeb to access it without opening up a new one.
  • You are using Convert.ToInt32 on a user provided value. This will break if they don't enter a proper number, if they included commas, etc. Consider using int.TryParse so that you can more gracefully fail if they enter an invalid value.
  • You shouldn't use list.Items.Add() to add an item; you should use list.AddItem(). Items.Add is considered deprecated.
like image 55
Servy Avatar answered Nov 15 '22 10:11

Servy