European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Core Hosting :: Error When Published ASP.NET Core? See Below Tips!

clock November 5, 2019 05:38 by author Scott

At the past few years, we have discussed about common error that you can find when published .NET Core, the most common error is 502.5 – process failure error.

Startup errors with ASP.NET Core don’t provide much information either, at least not in a production environment. Here are 7 tips for understanding and fixing those errors.

1. There are two types of startup errors.

There are unhandled exceptions originating outside of the Startup class, and exceptions from inside of Startup. These two error types can produce different behavior and may require different troubleshooting techniques.

2. ASP.NET Core will handle exceptions from inside the Startup class.

If code in the ConfigureServices or Configure methods throw an exception, the framework will catch the exception and continue execution.

Although the process continues to run after the exception, every incoming request will generate a 500 response with the message “An error occurred while starting the application”.

Two additional pieces of information about this behavior:

- If you want the process to fail in this scenario, call CaptureStartupErrors on the web host builder and pass the value false.

- In a production environment, the “error occurred” message is all the information you’ll see in a web browser. The framework follows the practice of not giving away error details in a response because error details might give an attacker too much information. You can change the environment setting using the environment variable ASPNETCORE_ENVIRONMENT, but see the next two tips first. You don’t have to change the entire environment to see more error details.

3. Set detailedErrors in code to see a stack trace.

The following bit of code allows for detailed error message, even in production, so use with caution.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
           .CaptureStartupErrors(true) // the default
           .UseSetting("detailedErrors", "true")
           .UseStartup<Startup>();

4. Alternatively, set the ASPNETCORE_DETAILEDERRORS environment variable.

Set the value to true and you’ll also see a stack trace, even in production, so use with caution.

5. Unhandled exceptions outside of the Startup class will kill the process.

Perhaps you have code inside of Program.cs to run schema migrations or perform other initialization tasks which fail, or perhaps the application cannot bind to the desired ports. If you are running behind IIS, this is the scenario where you’ll see a generic 502.5 Process Failure error message.

These types of errors can be a bit more difficult to track down, but the following two tips should help.

6. For IIS, turn on standard output logging in web.config.

If you are carefully logging using other tools, you might be able to capture output there, too, but if all else fails, ASP.NET will write exception information to stdout by default. By turning the log flag to true, and creating the output directory, you’ll have a file with exception information and a stack trace inside to help track down the problem.

The following shows the web.config file created by dotnet publish and is typically the config file in use when hosting .NET Core in IIS. The attribute to change is the stdoutLogEnabled flag.

<system.webServer>
  <handlers>
    <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />

  </handlers>
  <aspNetCore processPath="dotnet" arguments=".\codes.dll"
              stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" />
</system.webServer>

Important: Make sure to create the logging output directory.

Important: Make sure to turn logging off after troubleshooting is complete.

7. Use the dotnet CLI to run the application on your server.

If you have access to the server, it is sometimes easier to go directly to the server and use dotnet to witness the exception in real time. There’s no need to turn on logging or set and unset environment variables.

Summary

Debugging startup errors in ASP.NET Core is a simple case of finding the exception. In many cases, #7 is the simplest approach that doesn’t require code or environment changes. FYI, we also have support latest ASP.NET Core on our hosting environment. Feel free to visit our site at https://www.hostforlife.eu.



European ASP.NET Core 3 Hosting :: Custom JSONConverter ASP.NET Core 3

clock October 17, 2019 07:17 by author Scott

With the introduction of ASP.NET Core 3.0 the default JSON serializer has been changed from Newtonsoft.Json to System.Text.Json. For projects and libraries switching to the new JSON serializer this change means more performance and the opportunity to rewrite our JsonConverters.

Serialization of concrete classes

Let's start with a simple one that can (de)serialize a concrete class Category. In our example we (de)serialize the property Name only.

public class Category
{
   public string Name { get; }

   public Category(string name)
   {
      Name = name;
   }
}

To implement a custom JSON converter we have to derive from the generic class JsonConverter<T> and to implement 2 methods: Read and Write.

public class CategoryJsonConverter : JsonConverter<Category>
{
   public override Category Read(ref Utf8JsonReader reader,
                                 Type typeToConvert,
                                 JsonSerializerOptions options)
   {
      var name = reader.GetString();

      return new Category(name);
   }

   public override void Write(Utf8JsonWriter writer,
                              Category value,
                              JsonSerializerOptions options)
   {
      writer.WriteStringValue(value.Name);
   }
}

The method Read is using the Utf8JsonReader to fetch a string, i.e. the name, and the method Write is writing a string using an instance of Utf8JsonWriter.

In both cases (i.e. during serialization and deserialization) the converter is not being called if the value is null so I skipped the null checks. The .NET team doesn't do null checks either, see JsonKeyValuePairConverter<TKey, TValue>.

Let's test the new JSON converter. For that we create an instance of JsonSerializerOptions and add our CategoryJsonConverter to the Converters collection. Next, we use the static class JsonSerializer to serialize and to deserialize an instance of Category.

Category category = new Category("my category");

var serializerOptions = new JsonSerializerOptions
{
    Converters = { new CategoryJsonConverter() }
};

// json = "my category"
var json = JsonSerializer.Serialize(category, serializerOptions);

// deserializedCategory.Name = "my category"
var deserializedCategory = JsonSerializer.Deserialize<Category>(json, serializerOptions);

Serialization of generic classes

The next example is slightly more complex. The property we are serializing is a generic type argument, i.e. we can't use methods like reader.GetString() or writer.WriteStringValue(name) because we don't know the type at compile time.

In this example I've changed the class Category to a generic type and renamed the property Name to Key:

public class Category<T>
{
   public T Key { get; }

   public Category(T key)
   {
      Key = key;
   }
}

For serialization of the generic property Key we need to fetch a JsonSerializer<T> using the instance of JsonSerializerOptions.

public class CategoryJsonConverter<T> : JsonConverter<Category<T>>
{
   public override Category<T> Read(ref Utf8JsonReader reader,
                                    Type typeToConvert,
                                    JsonSerializerOptions options)
   {
      var converter = GetKeyConverter(options);
      var key = converter.Read(ref reader, typeToConvert, options);

      return new Category<T>(key);
   }

   public override void Write(Utf8JsonWriter writer,
                              Category<T> value,
                              JsonSerializerOptions options)
   {
      var converter = GetKeyConverter(options);
      converter.Write(writer, value.Key, options);
   }

   private static JsonConverter<T> GetKeyConverter(JsonSerializerOptions options)
   {
      var converter = options.GetConverter(typeof(T)) as JsonConverter<T>;

      if (converter is null)
         throw new JsonException("...");

      return converter;
   }
}

The behavior of the generic JSON converter is the same as before especially if the Key is of type string.

Deciding the concrete JSON converter at runtime

Having several categories with different key types, say, string and int, we need to register them all with the JsonSerializerOptions.

var serializerOptions = new JsonSerializerOptions
                        {
                           Converters =
                           {
                              new CategoryJsonConverter<string>(),
                              new CategoryJsonConverter<int>()
                           }
                        };

If the number of required CategoryJsonConverters grows to big or the concrete types of the Key are not known at compile time then this approach is not an option. To make this decision at runtime we need to implement a JsonConverterFactory. The factory has 2 method: CanConvert(type) that returns true if the factory is responsible for the serialization of the provided type; and CreateConverter(type, options) that should return an instance of type JsonConverter.

public class CategoryJsonConverterFactory : JsonConverterFactory
{
   public override bool CanConvert(Type typeToConvert)
   {
      if (!typeToConvert.IsGenericType)
         return false;

      var type = typeToConvert;

      if (!type.IsGenericTypeDefinition)
         type = type.GetGenericTypeDefinition();

      return type == typeof(Category<>);
   }

   public override JsonConverter CreateConverter(Type typeToConvert,
                                                 JsonSerializerOptions options)
   {
      var keyType = typeToConvert.GenericTypeArguments[0];
      var converterType = typeof(CategoryJsonConverter<>).MakeGenericType(keyType);

      return (JsonConverter)Activator.CreateInstance(converterType);
   }
}

Now, we can remove all registrations of the CategoryJsonConverter<T> from the options and add the newly implemented factory.

Category<int> category = new Category<int>(42);

var serializerOptions = new JsonSerializerOptions
{
    Converters = { new CategoryJsonConverterFactory() }
};

// json = 42
var json = JsonSerializer.Serialize(category, serializerOptions);

// deserialized.Key = 42
var deserialized = JsonSerializer.Deserialize<Category<int>>(json, serializerOptions);

In the end the implementation of a custom converter for System.Text.Json is very similar to the one for Newtonsoft.Json. The biggest difference here is the non-existence of a non-generic JsonConverter but for that we've got the JsonConverterFactory.

Actually, there is a non-generic JsonConverter which is the base class of the JsonConverter<T> and the JsonConverterFactory but we cannot (and should not) use this class directly because its constructor is internal.



European ASP.NET Core Hosting :: Paging Using Repeater Control In ASP.NET With And Without Stored Procedure

clock October 16, 2019 11:06 by author Peter

By default, pagination is not enabled in a Repeater control. We have to write custom pager control to use paging in a Repeater control. Here, I will explain how to implement paging in Repeater control in ASP.NET with and without a stored procedure. I am using Visual Studio 2019 to create the application.

Step 1
First, we have to create a table “tblCustomers” to test the paging in the repeater control.
CREATE TABLE [dbo].[tblCustomers]( 
[Id] [int] NOT NULL, 
[Name] [nvarchar](50) NULL, 
[Company] [nvarchar](50) NULL, 
[Phone] [nvarchar](50) NULL, 
[Address] [nvarchar](50) NULL, 
[Country] [nvarchar](50) NULL, 
[Email] [nvarchar](50) NULL 


After creating the table, add some record to the table.

Step 2
Open Visual Studio and click on "Create a new project".
Select ASP.NET Web Application from templates and click on “Next”.
Then, give the project name as “AspRepeater” and then click “Create”.
Now, choose “Web Forms” from the template and click on “Create”.

ASP.NET Repeater Control without Stored Procedure

Step 3
Now, create a new weborm “RepeaterControl” and write the code following code in your “RepeaterControl.aspx” page.
Code for RepeaterControl.aspx page.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RepeaterControl.aspx.cs" Inherits=" AspRepeater.RepeaterControl" %> 

<!DOCTYPE html> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
<title>Repeater Control without Stored Procedure</title> 
</head> 
<body> 
<form id="form1" runat="server"> 
    <div> 
        <asp:Repeater ID="Repeater2" runat="server"> 
            <HeaderTemplate> 
                <table id="tbDetails" style="width: 100%; border-collapse: collapse;" border="1" cellpadding="5" cellspacing="0"> 
                    <tr style="background-color: lightgray; height: 30px; color: black; text-align: center"> 
                        <th>Id</th> 
                        <th>Customer Name</th> 
                        <th>Company Name</th> 
                        <th>Phone</th> 
                        <th>Address</th> 
                        <th>E-Mail</th> 
                    </tr> 
            </HeaderTemplate> 
            <ItemTemplate> 
                <tr style="height: 25px;"> 
                    <td> 
                        <%#Eval("Id").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Name").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Company").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Phone").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Address").ToString()%>, <%#Eval("Country").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Email").ToString()%> 
                    </td>                         
                </tr> 
            </ItemTemplate> 
            <FooterTemplate> 
                </table> 
            </FooterTemplate> 
        </asp:Repeater> 
    </div> 
    <br /> 
    <div style="text-align:center"> 
        <asp:Repeater ID="Repeater1" runat="server" OnItemCommand="Repeater1_ItemCommand"> 
            <ItemTemplate> 
                <asp:LinkButton ID="lnkPage" 
                    Style="padding: 8px; margin: 2px; background: lightgray; border: solid 1px #666; color: black; font-weight: bold" 
                    CommandName="Page" CommandArgument="<%# Container.DataItem %>" runat="server" Font-Bold="True"><%# Container.DataItem %> 
                </asp:LinkButton> 
            </ItemTemplate> 
        </asp:Repeater> 
    </div> 
</form> 
</body> 
</html> 


Code for RepeaterControl.aspx.cs,
using System; 
using System.Collections; 
using System.Configuration; 
using System.Data; 
using System.Data.SqlClient; 
using System.Web.UI.WebControls; 

namespace AspRepeater 

public partial class RepeaterControl : System.Web.UI.Page 
{  
    private int iPageSize = 15; 

    protected void Page_Load(object sender, EventArgs e) 
    { 
        if (!IsPostBack) 
        { 
            GetCustomers(); 
        } 
    } 

    private void GetCustomers() 
    { 
        DataTable dtData = new DataTable(); 
        string conString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString; 
        SqlConnection sqlCon = new SqlConnection(conString); 
        sqlCon.Open(); 
        SqlCommand sqlCmd = new SqlCommand("Select * From tblCustomers", sqlCon); 
        SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd); 
        sqlDa.Fill(dtData); 
        sqlCon.Close(); 

        PagedDataSource pdsData = new PagedDataSource(); 
        DataView dv = new DataView(dtData); 
        pdsData.DataSource = dv; 
        pdsData.AllowPaging = true; 
        pdsData.PageSize = iPageSize; 
        if (ViewState["PageNumber"] != null) 
            pdsData.CurrentPageIndex = Convert.ToInt32(ViewState["PageNumber"]); 
        else 
            pdsData.CurrentPageIndex = 0; 
        if (pdsData.PageCount > 1) 
        { 
            Repeater1.Visible = true; 
            ArrayList alPages = new ArrayList(); 
            for (int i = 1; i <= pdsData.PageCount; i++) 
                alPages.Add((i).ToString()); 
            Repeater1.DataSource = alPages; 
            Repeater1.DataBind(); 
        } 
        else 
        { 
            Repeater1.Visible = false; 
        } 
        Repeater2.DataSource = pdsData; 
        Repeater2.DataBind(); 
    } 
     
    protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e) 
    { 
        ViewState["PageNumber"] = Convert.ToInt32(e.CommandArgument); 
        GetCustomers(); 
    } 



ASP.NET Repeater Control with Stored Procedure

Step 4
By using a Stored Procedure, we can fetch only one-page records from the available records based on the page index. For example, if our table has 300 records and we need to display only 15 records per page, then we will fetch only 15 records based on the page index.

Script for the Stored Procedure,
CREATE PROCEDURE GetCustomer 
@PageIndex INT = 1, 
@PageSize INT = 15, 
@RecordCount INT OUTPUT 
AS 
BEGIN 
SET NOCOUNT ON; 
SELECT ROW_NUMBER() OVER(ORDER BY Id ASC)AS RowNumber,ID, 
Name,Company,Phone,Address,Country,Email 
INTO #Results FROM tblCustomers 
  
SELECT @RecordCount = COUNT(*) FROM #Results 
        
SELECT * FROM #Results WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1  
AND (((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1 
  
DROP TABLE #Results 
END 

Step 5
Now, create a new webform “RepeaterControl1” and write the following code in your “RepeaterControl1.aspx” page.

Code for RepeaterControl.aspx page.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RepeaterControl1.aspx.cs" Inherits="AspRepeater.RepeaterControl1" %> 

<!DOCTYPE html> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
<title>Repeater Control with Stored Procedure</title> 
</head> 
<body> 
<form id="form1" runat="server"> 
    <div> 
        <asp:Repeater ID="Repeater1" runat="server"> 
            <HeaderTemplate> 
                <table id="tbDetails" style="width: 100%; border-collapse: collapse;" border="1" cellpadding="5" cellspacing="0"> 
                    <tr style="background-color: lightgray; height: 30px; color: black; text-align: center"> 
                        <th>Id</th> 
                        <th>Customer Name</th> 
                        <th>Company Name</th> 
                        <th>Phone</th> 
                        <th>Address</th> 
                        <th>E-Mail</th> 
                    </tr> 
            </HeaderTemplate> 
            <ItemTemplate> 
                <tr style="height: 25px;"> 
                    <td> 
                        <%#Eval("Id").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Name").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Company").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Phone").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Address").ToString()%>, <%#Eval("Country").ToString()%> 
                    </td> 
                    <td> 
                        <%#Eval("Email").ToString()%> 
                    </td> 
                </tr> 
            </ItemTemplate> 
            <FooterTemplate> 
                </table> 
            </FooterTemplate> 
        </asp:Repeater> 
    </div> 
    <br /> 
    <div style="text-align:center"> 
        <asp:Repeater ID="Repeater2" runat="server" OnItemCommand="Repeater2_ItemCommand"> 
            <ItemTemplate> 
                <asp:LinkButton ID="lnkPage" 
                    Style="padding: 8px; margin: 2px; background: lightgray; border: solid 1px #666; color: black; font-weight: bold" 
                    CommandName="Page" CommandArgument="<%# Container.DataItem %>" runat="server" Font-Bold="True"><%# Container.DataItem %> 
                </asp:LinkButton> 
            </ItemTemplate> 
        </asp:Repeater> 
    </div> 
</form> 
</body> 
</html> 

Code for RepeaterControl1.aspx.cs.
using System; 
using System.Collections.Generic; 
using System.Configuration; 
using System.Data; 
using System.Data.SqlClient; 
using System.Web.UI.WebControls; 

namespace AspRepeater 

public partial class RepeaterControl1 : System.Web.UI.Page 

    private int iPageSize = 15; 
    protected void Page_Load(object sender, EventArgs e) 
    { 
        if (!IsPostBack) 
        { 
            this.GetCustomers(1); 
        } 
    } 

    private void GetCustomers(int iPageIndex) 
    { 
        string conString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString; 
        SqlConnection sqlCon = new SqlConnection(conString); 
        sqlCon.Open(); 
        SqlCommand sqlCmd = new SqlCommand("GetCustomer", sqlCon); 
        sqlCmd.CommandType = CommandType.StoredProcedure; 
        sqlCmd.Parameters.AddWithValue("@PageIndex", iPageIndex); 
        sqlCmd.Parameters.AddWithValue("@PageSize", iPageSize); 
        sqlCmd.Parameters.Add("@RecordCount", SqlDbType.Int, 4); 
        sqlCmd.Parameters["@RecordCount"].Direction = ParameterDirection.Output; 
        IDataReader iDr = sqlCmd.ExecuteReader(); 
        Repeater1.DataSource = iDr; 
        Repeater1.DataBind(); 
        iDr.Close(); 
        sqlCon.Close(); 
        int iRecordCount = Convert.ToInt32(sqlCmd.Parameters["@RecordCount"].Value); 

        double dPageCount = (double)((decimal)iRecordCount / Convert.ToDecimal(iPageSize)); 
        int iPageCount = (int)Math.Ceiling(dPageCount); 
        List<ListItem> lPages = new List<ListItem>(); 
        if (iPageCount > 0) 
        { 
            for (int i = 1; i <= iPageCount; i++) 
                lPages.Add(new ListItem(i.ToString(), i.ToString(), i != iPageIndex)); 
        } 
        Repeater2.DataSource = lPages; 
        Repeater2.DataBind(); 
    } 

    protected void Repeater2_ItemCommand(object source, RepeaterCommandEventArgs e) 
    { 
        int iPageIndex = Convert.ToInt32(e.CommandArgument); 
        GetCustomers(iPageIndex); 
    } 

 



European ASP.NET Core Hosting :: TextBox Autocomplete with .NET Core 3.0

clock October 11, 2019 11:56 by author Peter

.NET Core 3.0 is the latest version of .NET Core and now supports WinForms and WPF. This sample shows how you can perform fill data to Autocomplete TextBox in another thread without slow down the main UI (User Interface). With this sample, you can do a better user experience for the end-user.

TextBox Autocomplete
Autocomplete helps the user to search/type from a know list. In my application, I build a list to Autocomplete with > 10.000 items and is very fast even on slow computers.

Autocomplete is an old feature, but this POST will demonstrate how to perform his use to load data fastly already in NET Core 3.0.

When you fill a Collection, if you have a huge suggestion list, this will make the UI (User Interface) freezes. But if you process in another thread the UI will not have any issues.

More technical information you can have here.

How it works

Like the other POST what uses a delegate, here, we use another thread to load data and delegate to bind the Autocomplete Collection in the current UI thread.
using System;  
using System.Data.SqlClient;  
using System.Drawing;  
using System.Windows.Forms;  
 
namespace TextBoxWithAutoComplete  
{  
 
    /// <summary>  
    /// 10-10-2019  
    /// </summary>  
    public partial class Form1 : Form  
    {  
 
        private TextBox textBox1;  
        public Form1()  
        {  
            InitializeComponent();  
 
            textBox1 = new TextBox  
            {  
                Location = new Point(0, 0),  
                Size = new Size(100, 32),  
                Visible = true,  
                TabIndex = 0  
            };  
            Controls.Add(textBox1);  
 
            Load += Form1_Load;  
        }  
 
        public void Form1_Load(object sender, EventArgs e)  
        {  
            Show(); // You need to show the form to avoid a thread error  
 
            LoadData(); // Start to load Data  
        }  
 
        private SqlConnection GetConnection()  
        {  
            // Init your connection  
            var oCnn = new SqlConnection  
            {  
                ConnectionString = "YOUR_CONNECTION_STRING"  
            };  
            oCnn.Open();  
            return oCnn;  
        }  
 
 
        #region TreadSafeLoading  
        private delegate void UpdateUIDelegate(AutoCompleteStringCollection myCollection);  
 
        /// <summary>  
        /// Load Data - You can make public to load as you need  
        /// </summary>  
        private void LoadData()  
        => // Start this process in a new thread  
            new System.Threading.Thread(() => OutOfThreadProcess()).Start();  
        // You can start others, every one in a new thread!  
 
        /// <summary>  
        /// Start fill in another Thread  
        /// </summary>  
        private void OutOfThreadProcess()  
        {  
            // inialize the collection  
            var myCollection = new AutoCompleteStringCollection();  
            using var oCnn = GetConnection();  
 
            // Start your SQL Query  
            var cmd = new SqlCommand($"Select [FirstName] + ' ' + [LastName] as [contactName] From [AdventureWorks].[Person].[Contact] Order By [FirstName], [LastName]", oCnn);  
 
            // Read and fill the collection  
            using var reader = cmd.ExecuteReader();  
            while (reader.Read())  
                myCollection.Add(reader.GetString(0));  
 
            // Invoke in a UI thread  
            _ = Invoke(new UpdateUIDelegate(UpdateUIInvoke), myCollection);  
        }  
 
        /// <summary>  
        /// Current UI Thread threatment  
        /// </summary>  
        /// <param name="myCollection"></param>  
        private void UpdateUIInvoke(AutoCompleteStringCollection myCollection)  
        {  
            // Setup up in corrent UI Thread  
            textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;  
            textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;  
            textBox1.AutoCompleteCustomSource = myCollection;  
#if (IS_TELERIK_RadTextBoxControl)  
            // If you use Telerik  
            // I found an issue in Telerik by Progress, without fix.  
            if (ParentForm != null)  
                ParentForm.FormClosing += new FormClosingEventHandler(UIFormClosing);  
#endif  
        }  
#if (IS_TELERIK_RadTextBoxControl)  
        private void UIFormClosing(object sender, FormClosingEventArgs e) => textBox1.AutoCompleteCustomSource = null;  
 
#endif  
        #endregion  
 
    }  
}  

Observation

When you use this technic may you receive errors if you run the new thread without fire the Show() method from the form, this occurs because the current window(form) hasn't the Handle initialized.

Conclusion
I design this technic when I upgrade to .NET Core 3 and develop a fix for the FileSystemWatcher event that fires in a new thread, so I took the same idea to make Autocomplete load collection works in a new thread.



European ASP.NET Core Hosting :: Knowing about WinForms and .NET Core 3.0

clock October 11, 2019 09:29 by author Scott

Desktop support for .NET Core 3.0 has been in preview for some time, it is slated to be released later this year. As per indicators by Microsoft, .NET Core will receive more updates compared to full .NET Framework, keeping this in mind, it makes sense to start thinking about migrating existing applications and creating new ones on .NET Core if the application still has some years to go.

Desktop support in .NET Core has not been completely migrated yet; however, it is possible to create and migrate WinForms applications using the preview bits. In this article, we'll consider the creation and migration of a WinForms application in .NET Core 3.0 that uses ComponentOne controls.

Creating a New .NET Core 3.0 Application

To create a new .NET Core 3.0 application, it's recommended to download VS 2019 and the nightly build of the .NET Core 3.0 SDK. Make sure that you’ve installed the .NET Framework 4.7.2 and .NET Core 2.1 development tools in the Visual Studio Installer. This software will be necessary whether you plan on creating a new project or migrating an existing one to .NET Core 3.0.

The simplest way to work with .NET Core 3.0 (for now) is to use dotnet.exe command line utility. It can be used to create a new project, add/restore dependencies, build, etc.

.NET Core 3 - Using x64 and x86 Versions

Visual Studio uses the appropriate version depending on your .NET Core 3 project’s target platform – x86 or x64. It uses last installed version for both platforms. So, if you intend to build your project for both platforms, you must download and install both platform SDK versions with the same version.

These are the typical paths for .NET Core 3 command line utility:

  • c:\Program Files\dotnet\dotnet.exe - for x64 version of .Net Core 3
  • c:\Program Files (x86)\dotnet\dotnet.exe- for x86 version of .Net Core 3

Let’s use x64 version of dotnet.exe to simplify it for further description.

Create a New Visual Studio Project

First, you’ll need to open the Visual Studio Developer Command Prompt to create a project through the command line. Currently, the tooling for Visual Studio is very limited in its support of .NET Core 3.0, so it’s easiest to create a project through the command line interface.

First, we’ll create the project:

“c:\Program Files\dotnet\dotnet.exe” **new** winforms -o TestAppWinFormsCore

Once this is finished, we’ll navigate into the project directory:

cd TestAppWinFormsCore

Finally, we can run the project to make sure that it works:

“c:\Program Files\dotnet\dotnet.exe” run

Now that the project has been created, we can use Visual Studio 2019 to open it and modify its contents. 

In the Visual Studio 2019, open the TestAppWinFormsCore.csproj file we just created.

You should see something like this in Visual Studio:

.NET Core 3.0 uses a new project type and has no design-time support currently, so the process of adding controls will be a little different than what you may be accustomed to. We need to add C1 libraries manually to the project to make use of them, also, we should add the controls manually to Form1.cs because of missing design-time support.

Because of this, let’s use a trick. We'll add the classic .NET Framework WinForms project in order to use its Form designer:

1. Right-click on Solution node and Add – New Project… - Windows Forms Desktop project (with .Net Framework, say version 4.0). The name of new project is by default WindowsFormsApp1.

2. Remove the existing Form1 from WindowsFormsApp1 project

3. Add Form1.cs from TestAppWinFoirmsCore project as link:

After that, the following view of Solution Explorer appears:

Now, we can edit Form1 form in the usual way:

Now, remove unneeded “Hello .NET Core!” label and add some C1 control, for example C1DockingTab:

Launch WindowsFormsApp1 application and observe C1DockingTab on Form1. But this will be a .Net Framework 4 application.

Adding C1DockingTab caused adding C1.Win.C1Command.4 reference to WindowsFormsApp1 project. Therefore, the same reference should be added to TestAppWinFormsCore project also. For this let’s take a look in the properties of the C1.Win.C1Command.4 reference (right-click – Properties…) and find the path to the assembly. It looks like C:\Program Files (x86)\ComponentOne\WinForms Edition\bin\v4.0\C1.Win.C1Command.4.dll. Add this reference to the TestAppWinFormsCore project (right-click on Dependencies – Add reference… - Browse… - choose C:\Program Files (x86)\ComponentOne\WinForms Edition\bin\v4.0\C1.Win.C1Command.4.dll).

You should be able to run the code at this point, though you’ll notice a ComponentOne nag screen since the TestAppWinFormsCore project doesn’t contain any licensing information.

We can correct this by adding a licenses.licx file to the project. To do so, right-click on TestAppWinFormsCore project and select Add -> Existing Items. And browse the licenses.licx file from WindowsFormsApp1/Properties folder.

Build and rerun the app and you should no longer see a nag screen.

And now this is a genuine .NET Core 3.0 WinForms app. You can see this in the Modules window. All system references are from C:\Program Files\dotnet... folder.

Migrating an Existing Project to .NET Core 3.0

It is possible to migrate an existing project to .NET Core 3.0, though the process may require a few more steps than you would expect. Also, before trying to migrate a project, it’s worth running Microsoft’s portability analyzer tool on the project you want to convert.

The tool can give you an idea (ahead of time) how compatible your project will be with .NET Core 3.0, and it points out potential problems you may run into (included unsupported APIs).

If you’ve made up your mind to try to migrate a project, it’s easiest to begin the process by creating a project through dotnet.exe as described above.Let’s look at the WeatherChart sample migration. This sample demonstrates the C1FlexChart control possibilities.

First, we’ll create a new DotNetCore3FlexChart project from the command line:

“c:\Program Files\dotnet\dotnet.exe” **new** winforms -o DotNetCore3FlexChart

Once this is finished, we’ll navigate into the project directory and open DotNetCore3FlexChart.csproj from Visual Studio 2019.

Next, add the WeatherChart project to the DotNetCore3FlexChart solution. WeatherChart project is placed in Documents\ComponentOne Samples\WinForms\C1FlexChart\CS\WeatherChart\WeatherChart\WeatherChart.csproj by default.

Here, we'll use the WeatherChart project in our .NET Core 3.0 project. Therefore, the WeatherChart project reference should be added to DotNetCore3FlexChart dependencies (right-click on Dependencies – Add Reference… - Projects - WeatherChart)

After that, open Project.cs from DotNetCore3FlexChart project and change the following line:

Application.Run(new Form1()); 

by 

Application.Run(new WeatherChart.Form1()); 

It means that the .NET Core 3.0 app (DotNetCore3FlexChart) will run WeatherChart.Form1 from WeatherChart assembly instead of own Form1\.

That’s all!

If you run the WeatherChart project it will be launched as .NET Framework 4.0 app.

But if you run the DotNetCore3FlexChart project then the WeatherChart assembly will be launched in .NET Core 3.0 environment.

.NET Core 3.0 Preview Caveats

Using the .NET Core 3.0 Preview for any kind of day-to-day work isn’t recommended at this point, as it’s obviously still work in progress. As the steps above illustrate, much of the project creation and migration processes require a lot of manual configuration from the user, and it’s possible to find some bugs and unfinished implementations presently.The lack of designer support also makes working with the preview somewhat difficult, though Microsoft has committed to adding this feature in the coming months.

Overall, .NET Core 3.0 will be an important change for developers, though this preview is merely the first step.



ASP.NET Core Hosting :: How to Upload File using C# | SFTP Server

clock March 4, 2019 07:56 by author Scott

Although there are many Graphical Tools available for sending files to a server using SFTP. But as a developer, we may have a scenario where we need to upload a file to SFTP Serverfrom our Code.

A few days ago a job assigned to me was to develop a Task Scheduler for generating XML files daily on a specific time of the day & send these files on a Remote Server using File Transfer Protocol in a secure way.

In .Net Framework there are many Libraries available for uploading files to another machine using File Transfer Protocol but most of the libraries don’t work with .Net Core. In this Tutorial, we will develop a very simple SFTP client using C# for .Net Core.

Before start let’s have a quick look at SFTP.

What is SFTP?

SFTP stands for SSH File Transfer Protocol or Secure File Transfer Protocol. It is a protocol used to transfer files between remote machines over a secure shell.

 

In almost all cases, SFTP is preferable over FTP because of security features. FTP is not a secure protocol & it should only be used on a trusted network.

Choosing Library for C#

A lot of search & after testing many libraries I finally met with SSH.NET which was working perfectly with .Net Core 2.2 project & the good thing was that It does its job in a very few lines of Code.

So we’ll use SSH.NET

What is SSH.NET?

SSH.NET is an open-source library available at Nuget for .NET to work over SFTP. It is also optimized for parallelism to achieve the best possible performance. It was inspired by Sharp.SSH library which was ported from Java. This library is a complete rewrite using .Net, without any third party dependencies.

Here are the features of SSH.NET: 

Creating Project

I’m in love with VS Code right after its first release so I’m going to use VS Code for creating project to upload/transfer a file to a remote server using SFTP.

Create a console application using this command

dotnet new console

Installing SSH.NET

I won’t recommend you to install the latest version of SSH.NET. It has a bug, it can be stuck on transferring the file to the remote location.

version 2016.0.0 is perfect. 

run this command to install the library from NuGet

using package manager

Install-Package SSH.NET -Version 2016.0.0

or using .Net CLI

dotnet add package SSH.NET --version 2016.0.0

Code

Finally, It’s time to create a class for SFTP Client Code.

Create a file with the name as “SendFileToServer” & add the below code

using Renci.SshNet

public static class SendFileToServer
{
// Enter your host name or IP here
private static string host = "127.0.0.1";

// Enter your sftp username here
private static string username = "sftp";

// Enter your sftp password here
private static string password = "12345";
public static int Send(string fileName)
{
var connectionInfo = new ConnectionInfo(host, "sftp", new PasswordAuthenticationMethod(username, password));

// Upload File
using (var sftp = new SftpClient(connectionInfo)){

sftp.Connect();
//sftp.ChangeDirectory("/MyFolder");
using (var uplfileStream = System.IO.File.OpenRead(fileName)){
sftp.UploadFile(uplfileStream, fileName, true);
}
sftp.Disconnect();
}
return 0;
}
}

Now you can call this Method to transfer a file to SFTP Server like this

SendFileToServer.Send("myFile.txt");

“myFile.txt” is the name of the file which should be located in your project root directory. 



European ASP.NET Core Hosting :: How to Use HTTP-REPL tool to test WEB API in ASP.NET Core 2.2

clock February 26, 2019 07:37 by author Scott

Today there are no tools built into Visual Studio to test WEB API. Using browsers, one can only test http GET requests. You need to use third-party tools like PostmanSoapUIFiddler or Swagger to perform a complete testing of the WEB API. In ASP.NET Core 2.2, a CLI based new dotnet core global tool named “http-repl” is introduced to interact with API endpoints. It’s a CLI based tool which can list down all the routes and execute all HTTP verbs. In this post, let’s find out how to use HTTP-REPL tool to test WEB API in ASP.NET Core 2.2.

HTTP-REPL Tool to test WEB API in ASP.NET Core 2.2

The “http-repl” is a dotnet core global tool and to install this tool, run the following command. At the time of writing this post, the http-repl tool is in preview stage
and available for download at 
dotnet.myget.org

dotnet tool install -g dotnet-httprepl --version 2.2.0-* --add-source https://dotnet.myget.org/F/dotnet-core/api/v3/index.json

Once installed, you can verify the installation using the following command.

dotnet tool list -g



Now the tool is installed, let’s see how we can test the WEB API. For this tool to work properly, the prerequisite here is that your services will have Swagger/OpenAPI available that describes the service.

We need to add this tool to web browser list so that we can browse the API with this tool. To do that, follow the steps given in the below image.



The location of HTTP-REPL tool executable is "C:\Users\<username>\.dotnet\tools". Once added, you can verify it in the browser list.

Run the app (make sure HTTP REPL is selected in browser list) and you should see a command prompt window. As mentioned earlier, it’s a CLI based experience so you can use commands like dir, ls, cdand cls. Below is an example run where I start-up a Web API.

You can use all the HTTP Verbs, and when using the POST verb, you should set a default text editor to supply the JSON. You can set Visual Studio Code as default text editor using the following command.

pref set editor.command.default "C:\Program Files (x86)\Microsoft VS Code\Code.exe"

Once the default editor is set, and you fire POST verb, it will launch the editor with the JSON written for you. See below GIF.

You can also navigate to the Swagger UI from the command prompt via executing ui command. Like,

Similarly, you can also execute the DELETE and PUT. In case of PUT command, you should use following syntax and in the default code editor, supply the updated data.

> delete 2 //This would delete the record with id 2.
>
> put 2010 -h "Content-Type: application/json"

When you fire PUT command, the behavior is same as the POST verb. The text editor will open with the JSON written for you, just supply the updated value to execute PUT command.

Pros and Cons

Pros

  • Helps in debugging WEB API
  • Fast and quickly switch between API endpoints
  • Descriptive error response shown

Cons:

  • Dependency on Swagger/Open API specification
  • Not as informative as UI tools

After playing with this for a while, I strongly feel it’s command line version of the Swagger UI and it would be very handy when there are many API endpoints. You can easily navigate or switch between the APIs and execute it. 



European ASP.NET Core Hosting :: How to Measure and Report the Response Time of ASP.NET Core

clock November 8, 2018 09:57 by author Scott

Performance is a buzzword for APIs. One of the most important and measurable parameters of the API performance is the response time. In this article, we will understand how to add code to measure the response time of an API and then return the response time data to the end client.

What is the need for this?

So, let's take a moment to think why we would ever need such a feature to measure the Response time of an API. Following are some of the points that have been the inspiration for writing code to Capture response time.

  • You need to define the SLA (Service Level Agreements) for your API with your clients. The clients need to understand how much time  the API takes to respond back. The response time data over time can help us decide on an SLA for our API.
  • Management is interested in reports as to how fast or slow the application is. You need to have data to corroborate your claims. It is worth it to have reports on the performance of the application and to share it with Stakeholders.
  • The client needs to have the information of the Response time of the API so that they can track how much time is spent on the client and the Server.

You might also have encountered similar requests in your project and it is worthwhile looking at an approach to capture the response time for the API.

Where to add the code?

Let's explore a couple of approaches to capture the response time of our API focusing mostly on capturing the time spent in our API. Our objective is to calculate the time elapsed in milliseconds from the time the request is received by the Asp.net core runtime to the time the response is processed and sent back from the Server.

What factors are we ignoring?

It's important to understand that this discussion doesn't include the time spent in N/W, Time spent in IIS and Application Pool Startup. If the Application Pool wasn't up and running, then the first request can affect the overall response time of the API. There is an Application Initialization Module which we can make use of but that is out of scope for this article.

First Attempt

One very naive approach to capturing the response time of an API would be to add code to every API method at the start and end and then measure the delta to calculate the response time as shown 

// GET api/values/5   
[HttpGet]  
public IActionResult Get() {  
    // Start the watch   
    var watch = new Stopwatch();  
    watch.Start();  
    // Your actual Business logic   
    // End the watch  
    watch.Stop();  
    var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;  
} 

This code should be able to calculate the time spent in an operation. But this doesn't seem to be the right approach for the following reasons.

If an API has a lot of operations, then we need to add this code to multiple places which are not good for maintainability.

This code measures the time spent in the method only, it doesn't measure the time spent on other activities like middleware, filters, Controller selection, action method selection, Model binding etc.

Second Attempt

Let's try to improve the above code by centralizing the code in one place so that it is easier to maintain. We need to execute the response time calculation code before and after a method is getting executed. If you have worked with earlier versions of Asp.net Web API, you would be familiar with concepts of Filter. Filters allow you to run code before or after specific stages in the request processing pipeline.

We will implement a filter for calculating the Response time as shown below. We will create a Filter and use the OnActionExecuting to start the timer and then stop the timer in method OnActionExecuted, thus calculating the response time of the API.

public class ResponseTimeActionFilter: IActionFilter { 
    private const string ResponseTimeKey = "ResponseTimeKey"; 
    public void OnActionExecuting(ActionExecutingContext context) { 
        // Start the timer  
        context.HttpContext.Items[ResponseTimeKey] = Stopwatch.StartNew(); 
    } 
    public void OnActionExecuted(ActionExecutedContext context) { 
        Stopwatch stopwatch = (Stopwatch) context.HttpContext.Items[ResponseTimeKey]; 
        // Calculate the time elapsed  
        var timeElapsed = stopwatch.Elapsed; 
    } 
}  

This code is not a reliable technique for calculating the response time as it doesn't address the issue of calculating the time spent in execution of middleware, controller selection, action method selection, model binding etc. The filter pipeline runs after the MVC selects the action to execute. So, it effectively doesn't instrument the time spent in the Other Asp.net pipeline. 

Third Attempt

We will use the Asp.net Core Middleware to Calculate the Response time of the API.

So, what is Middleware?

Basically, Middleware are software components which handle the Request/Response. Middleware is assembled into an application pipeline and serves in the incoming request. Each component does the following operations.

  • Chooses whether to pass the request to the next component in the pipeline. 
  • Can perform work before and after the next component in the pipeline is invoked.

If you have worked with HTTPModules or HTTPHandlers in ASP.NET, then you can think of Middleware as a replacement in ASP.NET Core. Some of the examples of middleware are -

  • MVC Middleware
  • Authentication
  • Static File Serving
  • Caching
  • CORS

 

 

We want to add code to start the timer once the request enters the ASP.NET Core pipeline and stop the timer once the response is processed by the Pipeline. Custom Middleware at the start of the request pipeline seems to be the best approach for getting the access to the request as early as possible and access until the last step is executed in the pipeline.

We will build a Response Time Middleware which we will add as the first Middleware to the request Pipeline so that we can start the timer as soon the request enters the Asp.net core pipeline.

What to do with the Response time data?

Once we capture the response time data we can process data in the following ways.

  1. Add the Response time data to a Reporting database or an analytics solution.
  2. Write the Response time data to a log file.
  3. Pass the response time data to a message queue which can further be processed by another application for reporting and analytics.
  4. Send the Response time information to the client applications consuming our Rest API using the Response headers.
  5. There may be other useful ways of using the response time data. Please leave a comment and tell me how you process the response time data in your application.

Let's write the code

We will write the code considering the following points.

  • Calculating the response time data for the API
  • Reporting the data back to client applications by passing the data in the Response headers.

Full code snippet for the ResponseTimeMiddleware is shown below.

public class ResponseTimeMiddleware { 
    // Name of the Response Header, Custom Headers starts with "X-"
 
    private const string RESPONSE_HEADER_RESPONSE_TIME = "X-Response-Time-ms";
 
    // Handle to the next Middleware in the pipeline
 
    private readonly RequestDelegate _next;
 
    public ResponseTimeMiddleware(RequestDelegate next) {
 
        _next = next;
 
    }
 
    public Task InvokeAsync(HttpContext context) {
 
        // Start the Timer using Stopwatch
 
        var watch = new Stopwatch();
 
        watch.Start();
 
        context.Response.OnStarting(() => {
 
            // Stop the timer information and calculate the time
  
            watch.Stop();
 
            var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;
 
            // Add the Response time information in the Response headers.
  
            context.Response.Headers[RESPONSE_HEADER_RESPONSE_TIME] = responseTimeForCompleteRequest.ToString();
 
            return Task.CompletedTask;
 
        });
 
        // Call the next delegate/middleware in the pipeline
  
        return this._next(context);
 
    }
 
}

Explanation of the code

The interesting part happens in the InvokeAsync method, We use Stopwatch class to start the stopwatch once the requests enter into the first middleware of the request and then stop the stopwatch once the request has been processed and the response is ready to be sent back to the client. OnStarting method provides an opportunity to write a custom code to add a delegate to be invoked just before response headers will be sent to the client.

Lastly, we add the Response time information in a Custom Header. We use the X-Response-Time-msheader as a Response Header. As a convention, the Custom Header starts with an X.

Conclusion

In this article, we understood how to leverage ASP.NET middleware to manage cross-cutting concerns like measuring the response time of the APIs. There are various other useful use cases of using middleware which can help to reuse code and improve the maintainability of the application.

/p>



ASP.NET 4.5 Hosting - HostForLIFE.eu :: How to Create a Database With Data Source Control in ASP.NET

clock March 29, 2016 21:10 by author Anthony

In this post we are going to talk about techniques for displaying data contained in the SQL Server database with ASP.NET. There are at least three ways commonly used to perform the data binding to server conrol in ASP.NET 4.5

Here are three ways:

  • Data Source Control (Declarative)
  • Code by Hand
  • Model Binding

but in this time I will explain how to create a database with the Data Source Control in ASP.NET 4.5


Web Config

Before going into the main discussion helps me informed beforehand that the connection string that is used to communicate with the database in ASP.NET contained in the configuration file "web.config". Here are the contents

file: Web.config


<?xml version="1.0"?>
<configuration>

<connectionStrings>
<add name="learn_webConnectionString" connectionString="Data Source=SOFT-ENGINEER;Initial Catalog=learning_web;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
</configuration>


Database Design

The database used in this post only use one of the table is very simple with the name "Category"

Data Source Control

Data Source Control in ASP.NET 4.5 used as a link between the database with controls for displaying data. Using this approach means that we do is get the data in a declarative rather than programmatic. To be more explicit, the following is a sample code

file: default.aspx


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TryingWebForm.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>Data Source Control</title>

</head>
<body>

<form id="form1" runat="server">

<div>

<p>The Declarative Way</p>

<asp:SqlDataSource ID="sdsCategory" runat="server" ConnectionString="<%$ ConnectionStrings:trying_webConnectionString %>"

SelectCommand="SELECT [id], [name_category] FROM [Category]"/>

<asp:GridView ID="gvCategoryDeclarative" runat="server" DataSourceID="sdsCategory" />

</div>

</form>

</body>

</html>

As seen in the above code, control "SqlDataSource" requires a connection string and a query command to be executed. In magic this control will connect to the database and execute commands query and the result was thrown into "GridView" by filling property "DataSourceID" with the Id of control SqlDataSource concerned. The image below is the result

 

HostForLIFE.eu ASP.NET 4.5 Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



Free ASP.NET 4.5 Cloud Hosting Spain - HostForLIFE.eu :: Count Number of Nodes in XML File in ASP.NET 4.5

clock May 6, 2014 06:00 by author Peter

Here I will explain how to count number of records in xml file in C# using ASP.NET 4.5 Cloud Hosting Spain or how to count number of nodes in xml file in asp.net using C# and VB.NET or count number of elements in xml file in C#.

In previous articles I explained insert xml data to sql table using stored procedure, Bind xml data to dropdown/gridview in asp.net, create online poll system with percentage graphs in asp.net and many articles relating to xml, Gridview, SQL, jQuery,asp.net, C#,VB.NET. Now I will explain how to count number of records in xml file in C# using ASP.NET.

To count number of nodes from xml file we need to write the code like as shown below

XmlDocument readDoc = new XmlDocument();
readDoc.Load(MapPath("Sample.xml"));
int count = readDoc.SelectNodes("CommentsInformation/Comments").Count;
lblcount.InnerHtml = "Number of Records: "+ count;

If you want to see it in complete example we need to write the code like as shown below
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table>
<tr>
<td style="width: 100px">
Name:</td>
<td style="width: 100px">
<asp:TextBox ID="txtName" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td style="width: 100px">
Email:</td>
<td style="width: 100px">
<asp:TextBox ID="txtEmail" runat="server"></asp:TextBox></td>
</tr>
<tr><td></td>
<td>
<asp:Button ID="btnSubmit" runat="server" OnClick="btnSubmit_Click" Text="Submit" /></td>
</tr>
</table>
<br />
<label id="lblcount" runat="server" />
</div>
</form>
</body>
</html>

After that add XML file to your application and give name as "Sample.xml" then add root element in xml file otherwise it will through error. Here I added CommentInformation as root element in XML file.
<?xml version="1.0" encoding="utf-8"?>
<CommentsInformation>
 </CommentsInformation>

After that add this namespace in codebehind

C# Code
using System;
using System.Xml;

After that add below code in code behind

protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(Server.MapPath("Sample.xml"));
XmlElement parentelement = xmldoc.CreateElement("Comments");
XmlElement name = xmldoc.CreateElement("Name");
name.InnerText = txtName.Text;
XmlElement email = xmldoc.CreateElement("Email");
email.InnerText = txtEmail.Text;

parentelement.AppendChild(name);parentelement.AppendChild(email);
xmldoc.DocumentElement.AppendChild(parentelement);
xmldoc.Save(Server.MapPath("Sample.xml"));
XmlDocument readDoc = new XmlDocument();
readDoc.Load(MapPath("Sample.xml"));
int count = readDoc.SelectNodes("CommentsInformation/Comments").Count;
lblcount.InnerHtml = "Number of Records: "+ count;
}

VB.NET Code
Imports System.Xml
Partial Class vbcode
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
End Sub
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim xmldoc As New XmlDocument()
xmldoc.Load(Server.MapPath("Sample.xml"))
Dim parentelement As XmlElement = xmldoc.CreateElement("Comments")
Dim name As XmlElement = xmldoc.CreateElement("Name")
name.InnerText = txtName.Text
Dim email As XmlElement = xmldoc.CreateElement("Email")
email.InnerText = txtEmail.Text
parentelement.AppendChild(name)
parentelement.AppendChild(email)
xmldoc.DocumentElement.AppendChild(parentelement)
xmldoc.Save(Server.MapPath("Sample.xml"))
Dim readDoc As New XmlDocument()
readDoc.Load(MapPath("Sample.xml"))
Dim count As Integer = readDoc.SelectNodes("CommentsInformation/Comments").Count
lblcount.InnerHtml = "Number of Records: " & count
End Sub
End Class



About HostForLIFE.eu

HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in