European ASP.NET MVC Hosting

BLOG about Latest ASP.NET MVC Hosting and Its Technology - Dedicated to European Windows Hosting Customer

ASP.NET MVC 6 Hosting - HostForLIFE :: Creating ASP.NET MVC APP With WCF Service

clock October 18, 2022 09:37 by author Peter

Use the following to create an ASP.NET MVC APP with a WCF Service using an ADO.NET Entity Data Model:
SQL Server DB -> WCF Service (ORM) -> MVC Application -> User (Browser).

This small app works in a 4-tier architecture as in the following:
    User Tier
    MVC app Tier
    WCF Service Tier
    SQL Server Tier

Project 1: WCF Project
Step 1
Go to VS 2012 and select "File" -> "New Website" then select "WCF Service" then provide the name “WcfMvc”.

Click "OK".

Step 2
Go to the Solution Explorer then go to "WcfMvc application" then right-click on it then seelct "Add" -> "Add new item" -> "Add ADO .Net Entity data model". Then click the "Add" button then place the file in the App_code Folder.

Step 3
Then the Entity Data Model Wizard will be shown. Select "Generate data from database" then click the "Next" button .

Step 4
Choose your data connection. I’m selecting My “ran” database of SqlServer 2012.
Activate the radio button “Yes include the sensitive data in the connection string”.
Save the connection string in the config file by enabling the check box “Save entity connection setting in web.config as:“ then click the "Next" button.

Or

go to the new connection and create your connection then provide the server name then provide the authentication type then select either Windows Authentication or SQL Authentication then provide the database name then click the "Ok" button. A new connection will then be generated.

Activate the Radio Button “Yes include the sensitive data in the connection string”.

Save the connection string in the config file by enabling the check box “save entity connection setting in web.config as: “ then click the "Next" button.

Step 5
Choose which database object you want in your model.

I’m selecting the “Customer” table. The table definition is as follows:
Create table customer
Custno int constraint pk primary key,
custname varchar(30) not null,
custcity varchar(30),
custbalance money);


You can use the above table or create your own table and use it

Then provide a Model Namespace of your choice.. I’m using “ranjeet” Namespace.

Click the "Finish" button.

Please ensure that in the Solution Explorer under the App_code folder the Model.edmx file has been created.

Your entity data model is ready for use.


Step 6
Go to Solution Explorer then expand the App_code Folder then go to the Iservice.cs file.

Step 7
Delete the Getdata() and GetDataUsingDataContract() methods.

Then

I’m writing one method GetCustomer() as follows.

Step 8
Then go to the Sevice.cs file and implement the method declared in the IService.cs interface.

In the Service.cs file right-click the Iservice Interface then select "Implement Interface" -> "Implement Interface".

Delete the already present method in the Service.cs the file.

And write the following code in the “public List<customer> GetCustomer()” method.

“ranEntities1” is a class name given when the connection is created.

Step 9
Open the Service.svc file and now run the project.
A new window will open; copy the URL present in that window and paste it into any text file. This URL will be used in the next project.

Project 2: MVC Application 4
Step 1

Ensure that the WCF project is open then start another instance of VS 2012. Then go to "File" -> "New" -> "Project..." then create an ASP.NET MVC 4 Web Application. Name it “MvcWcfApplication” then click "ok" Button. Then select the Project Template “Internet Application” then click the "Ok" button.

Step 2
Create a Proxy using “Add Service Reference” by right-clicking on MvcWcfApplication in the Solution Explorer.

(Note: Proxy is a class that converts a local request into a remote request.)

A new window will open. Paste the URL that you copied from the WcfMvc project into the Address TextBox then click "Go".

In other words, a proxy class is created successfully..

(Caution: if it has been created and in the project you can’t use the ServiceReference1 namespace Pl then don’t worry; it is a VS 2012 Automation Error. To solve it go to the Solution Explorer then select ServiceReference1 then right-click on it then select "Configure Service Reference". A new window will open then in it uncheck the “Reuse types in referenced assemblies” checkbox..)

A serviceReference1 will added into your project.

Step 3
Now add a new Controller then in Solution Explorer seelct "Controller" then right-click on it then select "Add Controller" (Ctrl+m, Ctrl+c).

Name it DbController. Click the "Add" button.


Step 4
Add the following code in the DbController.cs file.

Please build the project.

Step 5
Now right-click inside the Index() Method then select "Add View" (Ctrl+m, Ctrl+v) then click on “Create a Strongly Typed View” checkbox then select the Model Class we created, in other words “customer (MvcWcfApplication.ServiceReference1)” then select "Scaffold template List"then click the "Add" button.


Step 6
Run the application.
In the browser type: http://localhost:<Port>/Db

And see the results. All the data in the customer table is shown below the using WCF Service.

If you like this then please comment below.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Data Sharing Techniques In MVC

clock August 29, 2022 08:55 by author Peter

1) View Data

ViewData is a built-in object of the "ViewDataDictionary" class.
ViewData stores the data in key-value pairs

Example
public IActionResult Index() {
    ViewData["Name"] = "MVC";
    return View();
}


Output

2) View Bag
ViewBag is also used for sending Data from the controller to View.
ViewBag is developed based on Dynamic Typing.
No need to perform Type Casting
Use key as property

Example
public IActionResult ViewBagIndex() {
    ViewBag.Name = "MVC";
    return View();
}


Output


3) Temp Data
TempData is used to transfer the aata from one Action to Another Action at the time of redirection
TempData is an object of the "TempDataDictionary" class

Example
public ActionResult TempDataIndex() {
    TempData["Name"] = "MVC";
    return View();
}

Output

Please do leave a comment if you find it useful.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Pass Dynamically Added HTML Table Records List To Controller In ASP.NET MVC

clock August 23, 2022 07:37 by author Peter

Many times we need to post a list of records to controller instead of a single record to controller such as dynamically added html table records etc . Also I have learned on many forum posts regarding the problem in posting a list of records to controller, as many are saying while posting list of records we are getting only one record at controller instead of list of records . So by considering this requirement I have decided to write this article . Now let's learn step by step which helps beginners to learn how to get list of records into ASP.NET MVC controller .
 
Scenario
Let's consider we have a requirement in which a single user can add multiple orders of products at a time instead of  ordering one by one. So in this scenario we need to create one single view from a complex model that is from multiple models where one model can be used to hold customer information and the second model used to hold the list of records .

So let's demonstrate the preceding scenario by creating one simple ASP.NET MVC application

Step 1: Create an MVC Application.
Now let us start with a step by step approach from the creation of a simple MVC application as in the following:

    "Start", then "All Programs" and select "Microsoft Visual Studio 2015".

    "File", then "New" and click "Project", then select "ASP.NET Web Application Template", then provide the Project a name as you wish and click OK. After clicking, the following window will appear:

Step 2: Create Model Class
Now let us create the model class file named OrderModel.cs by right clicking on model folder as in the following screenshot:

Note:
It is not mandatory that Model class should be in Models folder, it is just for better readability; you can create this class anywhere in the solution explorer. This can be done by creating different folder names or without folder name or in a separate class library.

OrderModel.cs class file code snippet:
    /// <summary>  
       /// To hold order details  
       /// </summary>  
      public class OrderModel  
       {  
           public string ProductCode { get; set; }  
           public string ProductName { get; set; }  
           public Int16 Qty { get; set; }  
           public double Price { get; set; }  
           public double TotalAmount { get; set; }  
       }  
      public class OrderDetail  
       {  
           /// <summary>  
           /// To hold list of orders  
           /// </summary>  
           public List<OrderModel> OrderDetails { get; set; }  
      
       }


 Step 3: Add Controller Class.
Now let us add the MVC 5 controller as in the following screenshot:


After clicking on Add button it will show the window. Specify the Controller name as Order with suffix Controller.

Note:
The controller name must be having suffix as 'Controller' after specifying the name of controller. Now modify the default code in OrderController.cs class file to bind HTML table in view from strongly typed model class with list of records and getting those list of records into controller, after modifying code will look like as follows,

OrderController.cs
      public class OrderController : Controller  
        {  
            /// <summary>  
            /// Get list of records with View     
            /// </summary>  
            /// <returns></returns>  
            public ActionResult PlaceOrder()  
            {  
                List<OrderModel> objOrder = new List<OrderModel>()  
                {  
     new OrderModel {ProductCode="AOO1",ProductName="Windows Mobile",Qty=1,Price=45550.00,TotalAmount=45550.00 },  
    new OrderModel {ProductCode="A002",ProductName="Laptop",Qty=1,Price=67000.00,TotalAmount=67000.00 },  
    new OrderModel {ProductCode="A003",ProductName="LCD Television",Qty=2,Price=15000.00,TotalAmount=30000.00 },  
    new OrderModel {ProductCode="A004",ProductName="CD Player",Qty=4,Price=10000.00,TotalAmount=40000.00 }  
                };  
      
                OrderDetail ObjOrderDetails = new OrderDetail();  
                ObjOrderDetails.OrderDetails = objOrder;  
                return View(ObjOrderDetails);  
            }  
            /// <summary>  
            /// Get list of records from view  
            /// </summary>  
            /// <param name="Order"></param>  
            /// <returns></returns>  
            [HttpPost]  
            public ActionResult PlaceOrder(OrderDetail Order)  
            {  
      
      
                return View();  
            }  
        }


Step 4:
Creating strongly typed view named PlaceOrder using OrderDetail class. Right click on View folder of created application and choose add view, select OrderDetail model class and scaffolding template List   as,


Click on Add button then it will create the view named PlaceOrder , Now open the PlaceOrder.cshtml view, Then some default code you will see which is generated by MVC scaffolding template, Now modify default code to make as per our requirements, After modifying the code it will look like the following,

PlaceOrder.cshtml
@model GetHTMLTableRecordsInMVC.Models.OrderDetail  
@{  
    ViewBag.Title = "www.cpmpilemode.com";  
}  
<hr />  
@using (Html.BeginForm())  
{  
    @Html.AntiForgeryToken()  
 
    <div class="form-horizontal">  
        <div class="form-group">  
            <div class="col-md-offset-2 col-md-10 text-right">  
                 <input type="button" value="Add Product" class="btn btn-primary" />  
            </div>  
        </div>  
        <div class="form-group">  
            <div class="col-md-12">  
                <table class="table table-condensed table-hover">  
                    <tr>  
                        <th>  
                            Product Code  
                        </th>  
                        <th>  
                            Product Name  
                        </th>  
                        <th>  
                            Quantity  
                        </th>  
                        <th>  
                            Price  
                        </th>  
                        <th>  
                            Total Amount  
                        </th>  
                    </tr>  
                    @{  
                        //To make unique Id  
                        int i = 0;  
                        foreach (var item in Model.OrderDetails.ToList())  
                        {  
 
                            <tr>  
                                <td>  
 
 
                                    @Html.EditorFor(o => o.OrderDetails[i].ProductCode, new { @id = "ItemCode_" + i })  
                                </td>  
                                <td>  
                                    @Html.EditorFor(o => o.OrderDetails[i].ProductName, new { @id = "ProductName_" + i })  
                                </td>  
                                <td>  
                                    @Html.EditorFor(o => o.OrderDetails[i].Qty, new { @id = "Qty_" + i })  
                                </td>  
                                <td>  
                                    @Html.EditorFor(o => o.OrderDetails[i].Price, new { @id = "Price_" + i })  
                                </td>  
                                <td>  
                                    @Html.EditorFor(o => o.OrderDetails[i].TotalAmount, new { @id = "Price_" + i })  
                                </td>  
 
                            </tr>  
                            i++;  
                        }  
                    }  
                </table>  
            </div>  
        </div>  
        <hr />  
        <div class="form-group">  
            <div class="col-md-offset-2 col-md-10 text-center">  
                <input type="submit" value="Place Order" class="btn btn-primary" />  
            </div>  
        </div>  
    </div>  
 }


Common issues
While binding list of records your control Id's must be unique , otherwise same first record will repeat in all lists. So to avoid this we need to maintain  unique id's for control . As we have maintained in preceding view manually by using incremental i counter and model properties .

Now after adding the Model, View and controller into our project. The solution explorer will look like as follows,


Now we have done all coding to upload files . Step 5 : Now run the application. After running the application initial screen will look like as follows,


In preceding table we are adding orders (records) dynamically. Put break point on PlaceOrder action result method and click on Place Order button. Now the reference variable Order of OrderDetail class will show the four records in debug mode as,

In the preceding image you can see that four records list count which is coming from view because we have added four records into the table . Now Expand the OrderDetails node it will show the following records,

I hope from all preceding examples we have learned how to pass dynamically added HTML table records list to controller in ASP.NET MVC.

Note:

    Download the Zip file of the sample application for a better understanding.
    Add product button is just for scenario purpose , In next article I will explain how to add dynamic records into html table .
    Since this is a demo, it might not be using proper standards, so improve it depending on your skills.

Summary

I hope this article is useful for all readers. If you have any suggestions please contact me.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Output Caching in MVC

clock June 16, 2021 09:09 by author Peter

The main purpose of using Output Caching is to dramatically improve the performance of an ASP.NET MVC Application. It enables us to cache the content returned by any controller method so that the same content does not need to be generated each time the same controller method is invoked. Output Caching has huge advantages, such as it reduces server round trips, reduces database server round trips, reduces network traffic etc.

 
Keep the following in mind:
    Avoid caching contents that are unique per user.

    Avoid caching contents that are accessed rarely.

    Use caching for contents that are accessed frequently.

Let's take an example. My MVC application displays a list of database records on the view page so by default each time the user invokes the controller method to see records, the application loops through the entire process and executes the database query. And this can actually decrease the application performance. So, we can advantage of the "Output Caching" that avoids executing database queries each time the user invokes the controller method. Here the view page is retrieved from the cache instead of invoking the controller method and doing redundant work.
Cached Content Locations
 
In the above paragraph I said, in Output Caching the view page is retrieved from the cache, so where is the content cached/stored?
 
Please note, there is no guarantee that content will be cached for the amount of time that we specify. When memory resources become low, the cache starts evicting content automatically.
 
OutputCache label has a "Location" attribute and it is fully controllable. Its default value is "Any", however there are the following locations available; as of now, we can use any one.
 
1. Any   2. Client   3. Downstream   4. Server   5. None   6. ServerAndClient
 
With "Any", the output cache is stored on the server where the request was processed. The recommended store cache is always on the server very carefully. You will learn about some security related tips in the following "Don't use Output Cache".
 
How Output Cache Works
It is very important to understand how the "Output Cache" works. Anyone who invokes a controller method will get the same cached version of the view page. This means that the amount of work that the web server must perform to serve the view page is dramatically reduced.
 
For example, I have recorded a GIF here to show you how the same request is being made from three different clients (here three different browsers) and we are getting the same cached version (look at the time).

Okay, now let's look at the code, how I developed the one above, how to make any controller action or method cacheable. Here it is
[OutputCache(Duration = 10, VaryByParam = "name")]
 
Just add the preceding label before the controller method. The duration is in seconds, 10 seconds here. If you don't provide a "Duration" value then the default will be used, 60 seconds. I am using VaryByParam="name" and "VeryByParam" is something that makes many differences that you should care about that will be discussed later. "name" is a parameter passed by the user with the request to do database records filering.
 
Here is the complete code:
    [HttpPost]  
        [OutputCache(Duration = 10, VaryByParam = "name")]  
        public ActionResult SearchCustomer(string name = "")  
        {  
            NorthwindEntities db = new NorthwindEntities();  
            var model = from r in db.Customers  
                        where r.ContactName.Contains(name)  
                        select r;  
            if (model.Count() > 0)  
            {  
                return View(model);  
            }  
            else  
            {  
                return View();  
            }  
        }  


In the code above, I'm looking at the "name" parameter passed by the user and then, depending on the name, selecting matching records with a LINQ query and then checking if the model has the number of records greater than zero then send the model to the view else simply send the view (no model).
VaryByParam can be one of the following types:

1. VaryByParam = "none": Think of it like, we don't want to care about the form parameter or query string parameter passed by the user from the view page. If I use "none" then it will create the same cached version of the content for every user who visits the website, and the content will only change after a specified number of seconds (here 10 seconds).

Let's use [OutputCache(Duration = 10, VaryByParam = "none")] in the code above and look at the behavior.

In above GIF you can notice on second request to see list of records that contains "a" nothing happens, because it is displaying the cached data.
2. VaryByParam = "name": This property enables you to create different cached versions of the content when a form parameter or query string parameter varies. In other words if I find records matching "ce" string then a new cache will be created by replacing the older one, again if I find records matching "ab" string then a new cache will be created by replacing the last one ("ce" cached), no matter duration is elapsed or not.
 
Let's use [OutputCache(Duration = 10, VaryByParam = "name")] in code above and look at behavior.

In the above GIF note that on each new request with a different query string parameter or form parameter, a new cache is being created; look at the time it is changing. Here the use of the cache is that if I request the same thing that I requested previously then the cached version will be rendered, here it is:

In the above GIF note that nothing happens (look at the time) when I continuously request the same information, rendering the cached version.
3. VaryByParam = "*": We can use * for all parameters or a semi-colon separated list to cache various versions. This works very similar to the one above (VaryByParam="name").
    [OutputCache(Duration = 10, VaryByParam = "*")]  
    public ActionResult SearchCustomer(string name = "", string city = "")  
    {  
        NorthwindEntities db = new NorthwindEntities();  
        ...  

OR
    [OutputCache(Duration = 10, VaryByParam = "name; city")]  
    public ActionResult SearchCustomer(string name = "", string city = "")  
    {  
        NorthwindEntities db = new NorthwindEntities();  
        ...  

Both scenarios work the same, so use whichever one that makes you happy.
Check Web Page is Cache-able or not?
 
Fiddler is a great tool if you want to check whether a requested web page is cache-able or not, here is a GIF image of it.

In the above GIF you can see the GET request is not cacheable whereas the POST request is cacheable and with max-age: 10 seconds.
Don't use Output Cache
 
Here you will learn about some quick security related issues and their prevention.

Danger 1
We should always be careful while using "OutputCache", I will show you an example here. Let's look at the following controller action method and try finding security vulnerabilities.
    [OutputCache(Duration = 10, VaryByParam = "none")]  
        public ActionResult Profiles()  
        {  
            if (User.Identity.IsAuthenticated)  
            {  
                MembershipUser u = Membership.GetUser(User.Identity.Name);  
                ViewBag.welcomeNote = "Welcome back " + User.Identity.Name + ". Your last login date was " + u.LastLoginDate;  
            }  
            else  
            {  
                ViewBag.welcomeNote = "Welcome Guest";  
            }  
            return View();  
        }  
       


Now, I'm running the code above, see how the usernames are appearing in both (IE and Chrome) browsers, the GIF is given below. Username is also being cached and stored on the server for other users.

In the above controller action method we don't have a "VaryByCustom" or "Location" attribute with "OutputCache" to safeguard it, so by default it uses Location = OutputCacheLocation.Any that is dangerous in this case. If you are using membership in the web application then you should pay special attention. A few ways are given below, the first is more secure and recommendable.

1st Way
You can also take advantage of the VaryByCustom property in [OutputCache] by overriding HttpApplication.GetVaryByCustomString and checking HttpContext.Current.User.IsAuthenticated.

This is what I will create in the Global.asax.cs file:
    public override string GetVaryByCustomString(HttpContext context, string custom)  
    {  
        if (custom == "LoggedUserName")  
        {  
            if (context.Request.IsAuthenticated)  
            {  
                return context.User.Identity.Name;  
            }  
            return null;  
        }  
        return base.GetVaryByCustomString(context, custom);  
    }  


And then use it in the OutputCache attribute:
    [OutputCache(Duration = 10, VaryByParam = "none", VaryByCustom = "LoggedUserName")]  
    public ActionResult Profiles()  
    {  
        //...  
    }  

Now for every user logged in on the website OutputCache will create a separate version, and it works great. We can even use Duration, VaryByParam, VaryByCustom and Location attributes together to make it more productive, useful and secure.

We can also enable separate cache entries for each browser, VaryByCustom can be set to a value of "browser". This functionality is built into the caching module, and will insert separate cached versions of the page for each browser name and major version. You don't need to override HttpApplication.GetVaryByCustomString.
    [OutputCache(Duration = 10, VaryByParam = "none", VaryByCustom = "browser")]  
    public ActionResult Profiles()  
    {  
       ...  


2nd Way
See, this is less reliable but works. You should use Location = OutputCacheLocation.Client. If you don't, the login username will also be cached and stored on the server for other users and that is confusing & quite dangerous.

Here is the complete controller action method code.
    [OutputCache(Duration = 10, VaryByParam = "none", Location = OutputCacheLocation.Client)]  
    public ActionResult Profiles()  
    {  
        ...  
    }  

Note 1: POST requests are not cached on the client, in other words this will not work because it is a POST request and the caching location is on the client.
      [HttpPost]  
    [OutputCache(Duration = 10, VaryByParam = "name", Location = OutputCacheLocation.Client)]  
    public ActionResult SearchCustomer(string name = "")  
    {  
        ...  
    }  


Note 2: If you are trying to test client-side caching (like the one given above) and hitting F5 then you are losing the client cache. The way the client cache is supposed to work is that you have links on the site pointing to the Client action from some other views and when the user clicks on those links the cached version will be served.

Danger 2
If you want a more secure application then you should only enable caching for a page when the page does not require authorization. Normally, you require authorization for a page when you display personalized data in the page. Since you don't want personalized data to be shared among multiple users, don't cache pages that require authorization.
    [Authorize]  
    [OutputCache(Duration = 10, VaryByParam = "none")]  
    public ActionResult CreditCardDetails()  
    {  
        ...  
    }  


In the code above, you are combining OutputCaching and Authorize with an action method that contains your credit card information. And you know how OutputCaching stores data out of the database that is not as secure as a database. So you are broadcasting your private information to the entire world. Don't do it.

Creating Cache Profile
It is very difficult to change the rules (like Duration, VaryByParam, VaryByCustom, Location) used with "OutputCache" on each controller method when your large application has already been deployed.

So, there is an alternative to configure the OutputCache profile in the web.config file. By configuring output caching in the web configuration file, you can control it on one central location. You can create one cache profile and apply the profile to several controllers or controller actions. Also, you can modify the web configuration file without recompiling your application. Any changes to the web configuration file will be detected automatically and applied to the entire application.

In the following code you can see I have used a new attribute CacheProfile that maps to Cache10Seconds that is in web.config.
    [OutputCache(CacheProfile = "Cache10Seconds", VaryByCustom = "LoggedUserName")]  
    public ActionResult Profiles()  
    {  
       ...  

And then web.config:
    <system.web>  
      <caching>  
        <outputCacheSettings>  
            <outputCacheProfiles>  
                <add name="Cache10Seconds" duration="10" varyByParam="none"/>  
            </outputCacheProfiles>  
        </outputCacheSettings>  
      </caching>  
      ...  


Please note, I moved Duration, VaryByParam and Location (we can use it also) in web.config but not VaryByCustom and the reason is, it is used for overriding the rules.
Now, assume for any reason I want to disable caching for an entire application that has already been deployed to production, then you can simply modify the cache profiles defined in the web configuration file.
 
We can even disable it as in the following:

    <system.web>  
        <caching>  
            <outputCache enableOutputCache="false" =""/>  
            <outputCacheSettings>  
                  <outputCacheProfiles>  
                        <add name="Cache10Seconds" duration="10" varyByParam="none"/>                 
          </outputCacheProfiles>           
        </outputCacheSettings>  
      </caching>  

This approach is pretty good because rather than targeting any specific outputCacheProfile we can disable all at once, awesome.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: How To Create ASP.NET Core MVC Application?

clock April 26, 2021 07:06 by author Peter

In this article, we will learn how to create an ASP.NET Core MVC web application step by step. Prior to creating the application, let's know about the ASP.NET Core.

What is ASP.NET Core?
ASP.NET Core is an open source cross platform framework for developing and building web, cloud, IoT applications.
 
Why should we use ASP.NET Core?

  • ASP.NET is an open-source platform that runs on Microsoft .NET Core Framework.
  • We can build and run the ASP.NET core application on a cross platform environment such as Windows, MacOs, Linux etc.
  • We can build modern apps such as Cloud, IoT, Web apps, mobile backend etc. and those can be easily enabled to run over the cloud platform.
  • We can host applications on any modern platform such as docker, AKS, or any environment.
  • Saves the efforts of the developer by built-in features such as dependency injection, you can enable docker, containerization, swagger support in just one click.

 

Now let's start creating an ASP.NET Core MVC web application.
 
Step 1 - Open Visual Studio
Open Visual Studio ( I am using 2019)
Once the Visual Studio Opens, Then click on Continue Without Code as shown in the following image

Then from Visual Studio Menu, click on File => New Project, as shown in the following image

Click on the New Project, then the following window appears as shown in step 2.
 
Step 2 - Choose Project Template
You will see the two project templates,

  • ASP.NET Core Web App: This project template creates the web application with Razor pages without Model, View, Controller.
  • ASP.NET Core Web App (Model-View-Controller): This project template creates the web application with Model, View, Controller (MVC).


Choose the ASP.NET Core Web App(Model-View-Controller) Template as shown in the following image.

After choosing the project template click on Next.
 
Step 3 - Define Project Name and Location
In the project configuration window you will see the following options,
Project Name
Define any name for your project as per your choice.

Location

Choose the location to save the project files on your hard drive of the machine. I have chosen the Project/VS folder of the E drive of the machine, and obviously it's different on your computer.

Solution Name
Solution name is auto-defined based on the project name, but you can change the name based on your own choice.

Additionally, there is a checkbox, if you have checked it, then the solution file (.sln) and project files will be saved in the same folder. Now Choose the minimum details for ease of understanding as shown in the following image.


After defining the required details, click on the Next.
 
Step 4 - Choose the Target Framework
Choose the target framework .NET 5 which is the latest or you can choose based on your requirement, skip the other details for ease of understanding as shown in the following image.

After providing the required details, click the create button. It will create the ASP.NET Core MVC web application as shown in step 5.
 
Step 5 - Understanding ASP.NET Core MVC Folder Structure
The following is the default folder structure of the ASP.NET Core ASP.NET MVC application.

Let's understand preceding project folder structure in brief.
 
The wwwroot folder
The wwwroot is the default root folder for storing the static files related to the project and those files can be accessed programmatically with a relative path.
 
Controller Folder
The controller folder contains the controller classes where the operation related code written.
 
Model Folder
The Models Folder contains the domain or entity classes. Models can be written anywhere in the solution such as in separate class library or folder etc.
 
Views Folder
The Views folder holds the razor pages which are responsible for showing and getting the data from the users.
 
The appsettings.json File
The appsettings.json folder contains the configuration and secret details of the application.
 
Program.cs File

The Program.cs is the starting point of the application which will create the host for an application to run the application.
 
Startup.cs File
The Startup.cs file allows to configure the behaviour of the application such as defining the routes, dependency injection etc.
 
Step 6 - Run the ASP.NET Core MVC Application
You can run the application with default contents or let open the Index.cshtml file and put some contents there. Now press F5 on the keyboard or use the run option from Visual Studio to run the application in the browser.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Create Simple Web API In ASP.NET MVC

clock March 26, 2021 08:32 by author Peter

This article explains how to access data from a view to the controller's action method. The action method is a simple C# method that can be parameterized or without a parameter in the controller. We use two types of methods to handle our browser request; one is HTTP GET and another is HTTP POST. When we call an action method by a request's URL by the browser then the HTTP GET method will be called but when a request is from a button click event then the HTTP POST method will be called. So in this article, I am going to explaining how to access view input field data in the controller's action method when a HTTP POST request is called.

 
To understand how to access view input field data in the controller's action method (POST), we create a "Calculate Simple Interest" application. This application gets Principle, Rate and Time as user input and generates simple interest. So let's proceed with the application.
 
Create an action method in the CalculateSimpleInterest controller (CalculateSimpleInterestController.cs) that renders the view on the UI.
    public ActionResult SimpleInterest()  
    {  
        return View();  
    }  

Create a view to get user input from the UI, so the code is:
    <h2>Calculate Simple Interest</h2>  
    <fieldset>  
            <legend>Calculate Simple Interest</legend>  
        @using (Ajax.BeginForm("CalculateSimpleInterestResult","CalculateSimpleInterest",  
                                new AjaxOptions { UpdateTargetId = "divInterestDeatils" }))  
        {  
            <div id="divInterestDeatils"></div>  
            <ol>  
                <li>  
                    @Html.Label("Amount")  
                    @Html.TextBox("txtAmount")  
                </li>  
                <li>  
                    @Html.Label("Rate")  
                    @Html.TextBox("txtRate")  
                </li>  
                <li>  
                    @Html.Label("Year")  
                    @Html.TextBox("txtYear")  
                </li>  
            </ol>  
        <button>Calculate</button>  
        }     
    </fieldset>  


So now the screen is ready to get input and it shows it as:

 

Figure 1.1 Input screens to calculate simple interest

I will now explain the four ways to get the view's data in the controller action. These are:
    Using Traditional approach
    Using the FormCollection Object
    Using the Parameters
    Strongly type model binding to view

Using Traditional Approach
In the traditional approach we use the request object of the HttpRequestBase class. The request object has view input field values in name/value pairs. When we create a submit button then the request type POST is created and calls the POST method.

Figure 1.2 Requested Data

We have four data, those are in Name-Value pairs. So we can access these data in a POST method by passing the Name as an indexer in the Request and get values. Our POST method means the controller action that handles the POST request type is [HttpPost].
    [HttpPost]  
    public ActionResult CalculateSimpleInterestResult()  
    {  
        decimal principle = Convert.ToDecimal(Request["txtAmount"].ToString());  
        decimal rate = Convert.ToDecimal(Request["txtRate"].ToString());  
        int time = Convert.ToInt32(Request["txtYear"].ToString());  
       
        decimal simpleInteresrt = (principle*time*rate)/100;  
       
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + principle+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + time + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }  


When it executes, we get simple interest as the result as in the following:

Figure 1.3 Output screen after getting response

Using the FormCollection Object
We can also get post requested data by the FormCollection object. The FormCollection object also has requested data in the name/value collection as the Request object. To get data from the FormCollection object we need to pass it is as a parameter and it has all the input field data submitted on the form.
    [HttpPost]  
      
    public ActionResult CalculateSimpleInterestResult(FormCollection form)  
    {  
        decimal principle = Convert.ToDecimal(form["txtAmount"].ToString());  
        decimal rate = Convert.ToDecimal(form["txtRate"].ToString());  
        int time = Convert.ToInt32(form["txtYear"].ToString());  
       
        decimal simpleInteresrt = (principle*time*rate)/100;  
       
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + principle+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + time + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }


It also gives the same output as Figure 1.3 shows.
 
Using the Parameters

We can pass all input field names as a parameter to the post action method. The input field name and parameter name should be the same. These parameters have input field values that were entered by the user. So we can access view input field values from these parameters. The input field takes a string value from the user so the parameter should be a string type. There is no need to define a parameter in any specific sequence.
    [HttpPost]  
    public ActionResult CalculateSimpleInterestResult(string txtAmount, string txtRate, string txtYear)  
    {  
        decimal principle = Convert.ToDecimal(txtAmount);  
        decimal rate = Convert.ToDecimal(txtRate);  
        int time = Convert.ToInt32(txtYear);  
       
        decimal simpleInteresrt = (principle*time*rate)/100;  
       
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + principle+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + time + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }  


It also gives the same output as Figure 1.3 shows.
 
In all three approaches above we are parsing the string to a non-string type. If any of the parsing attempts fail then the entire action will fail. We are converting each value to avoid an exception but it also increases the amount of code. So we look at the fourth approach that would reduce the amount of code.
 
Strongly type model binding to view
 
We bind a model to the view; that is called strongly type model binding.
 
Step 1
Create a Model for Simple Interest
    namespace CalculateSimpleInterest.Models  
    {  
        public class SimpleInterestModel  
        {  
            public decimal Amount { get; set; }  
            public decimal Rate { get; set; }  
            public int Year { get; set; }  
        }  
    }  


Step 2
Create an action method that render a view on the UI
 
We are passing an empty model to be bound to the view.
    public ActionResult SimpleInterest()  
    {  
        SimpleInterestModel model = new SimpleInterestModel();  
        return View(model);  
    }  


Step 3
Create a strongly typed view that has the same screen as in Figure 1.1
    @model CalculateSimpleInterest.Models.SimpleInterestModel  
       
    @{  
        ViewBag.Title = "SimpleInterest";  
    }  
       
    <h2>Calulate Simple Interest</h2>  
       
    @using (Ajax.BeginForm("CalculateSimpleInterestResult","CalculateSimpleInterest",  
                                new AjaxOptions { UpdateTargetId = "divInterestDeatils" }))  
        {  
             
        <fieldset>  
            <legend>Calulate Simple Interest</legend>  
            <div id="divInterestDeatils"></div>  
       
            <div class="editor-label">  
                @Html.LabelFor(model => model.Amount)  
            </div>  
            <div class="editor-field">  
                @Html.EditorFor(model => model.Amount)            
            </div>  
       
            <div class="editor-label">  
                @Html.LabelFor(model => model.Rate)  
            </div>  
            <div class="editor-field">  
                @Html.EditorFor(model => model.Rate)            
            </div>  
       
            <div class="editor-label">  
                @Html.LabelFor(model => model.Year)  
            </div>  
            <div class="editor-field">  
                @Html.EditorFor(model => model.Year)             
            </div>  
            <p>  
                <input type="submit" value="Calculate" />  
            </p>  
        </fieldset>  
    }  
       
    @section Scripts {  
        @Scripts.Render("~/bundles/jqueryval")  
    }  

Step 4
Create an action method that handles the POST request and processes the data
 
In the action method we pass a model as the parameter. That model has UI input field data. Here we do not need to parse and do not need to write extra code.
    [HttpPost]  
    public ActionResult CalculateSimpleInterestResult(SimpleInterestModel model)  
    {  
        decimal simpleInteresrt = (model.Amount*model.Year*model.Rate)/100;  
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + model.Amount+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + model.Rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + model.Year + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }  

It also gives the same output as Figure 1.3 shows.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Understanding Separation Of Concern in ASP.NET MVC

clock February 22, 2021 06:01 by author Peter

What is Separation of Concern?
Wikipedia says “In computer science, separation of concerns (SoC) is a design principle for separating a computer program into distinct sections, such that each section addresses a separate concern. A concern is a set of information that affects the code of a computer program.”

As said concern is a set of information, in our application concern is known as modules or a set of responsibility, we use this principle to separate application module to manage scalable applications.

You can also think of separation the same as how we use layers in our application as follows:


However we can implement different tiers for databases as well.

The above architecture can be followed in any web or native (desktop) application, in order to use separation of concern.

How separation of concern in ASP.NET

A couple of years ago, Microsoft came up with ASP.NET MVC which is a superset of ASP.NET (now ASP.NET web form). Since before ASP.NET MVC there was Spring (JAVA), Ruby on Rail frameworks and may be others has already implemented MVC architecture.

ASP.NET MVC adds SoC for web (http) and separate Model (business), View(User Interface) and Controller (Processing data to view or vice versa), it gives responsibility to Model, View, Controller as follows :


You may have seen the above diagram in many articles. Herethe model is responsible to handle business logic, don’t get it confused with ViewModel as ViewModel are simple classes in ASP.NET MVC to bind strongly typed views.

Flexibility and its violation of SoC in ASP.NET MVC
As a ASP.NET MVC developer I feel it’s quite flexible to work with MVC as it’s a framework with extensibility as we can implement our own principles if required.

MVC framework uses loose coupling (another form of SoC) for every concern (modules). It’s recommended to use Model for business logic, controller for processing incoming requests and views to display information to end user.

But the actual problem is due to flexibility of ASP.NET MVC and it’s easy to violate these principles.

Examples of violation of MVC principle:

    Using ViewBag or ViewData for passing data from controller to view:
        // contoller  
        public ActionResult Index()   
        {  
                ViewBag.EmployeeData = getEmplyees(x => x.DOB > DateTime.Now);  
            }  
            // view  
        foreach(var employee in ViewBag.EmployeeData)  
        {  
            // using data  
        }  

    Above line of code doesn’t restrict developer, but it violates principle to use ViewModel to display data in view.

    Using business logic in controller:
        Public ActionResult Save(Employee model)  
        {  
            If(ModelState.IsValid)   
            {  
                _dbContext.Employees.Add(model)  
            }  
            Return RedirectToAction(“Success”);  
        }  

    Using above code, its violation of SRP because controller is having database logic to save information.

    Using business logic in view:
        @if(user.Role == ”Admin”)  
        {  
            //  
        }  
        Else   
        {  
            //  
        }  

    Using this we are using business logic in view which is only responsible to display information.

Apart from these, there area lot of code snippets you can find in your ASP.NET MVC project as well as online communities.

Recommendations

Where to put business logic:
It’s recommended to use a Service layer to implement business logic in your application as follows:
    public class EmployeeService   
    {  
        IRepository _employeeRepository;  
        public EmployeeService(IRepository employeeRepository)   
        {  
            this._employeeRepository = employeeRepository;  
        }  
        public IEnumeratble < Employee > GetEmplyee(int id)   
        {  
            return _employeeRepository.FindBy(x => x.ID == id).FirstOrDefault();  
        }…………..  
    }  


Repository pattern is a well known pattern for data access, here is a sample:
    public class Repository < T > : IRepository < T > where T: class   
    {  
        private DbContext Context;  
      
        public Repository(DbContext ctx)   
        {  
            Context = ctx;  
        }  
      
        public virtual IQueryable < T > GetAll()   
        {  
            IQueryable < T > query = Context.Set < T > ().AsQueryable();  
            return query;  
        }  
        public IQueryable < T > FindBy(System.Linq.Expressions.Expression < Func < T, bool >> predicate)   
        {  
            IQueryable < T > query = Context.Set < T > ().Where(predicate);  
            return query;  
        }
      
    }  


Repository can be wrapped with a unit of work to save final changes all together. Here is sample unit of work interface which can be implemented for convenience, however it’s not required.
    public interface IUnitOfWork  
    {  
        IRepository < TEntity > GetRepository < TEntity > () where TEntity: class;  
        void Save();  
    }  


And finally we can inject (using DI) service in controller to use business objects.
    public class EmployeeContoller   
    {  
        IService _employeeService;  
        Public EmployeeContoller(IService employeeService)   
        {  
            _employeeService = employeeService;  
        }…………  
    }  

I hope readers will avoidthe  above mentioned mistakes while working with ASP.NET MVC to deliver scalable applications.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: View Without Controller Action in MVC

clock February 19, 2021 12:18 by author Peter

In this quick article you will learn how a view can be rendered without its native Controller Action method.

Why do we need this?
Let's look at the following image.


In the image above, you can see that for each view we have a matching controller action. Each of these actions contains a single line of code. In fact, each of these actions contains exactly the same line of code. And this is completely unnecessary. Imagine what you will do when you have hundreds or thousands of views. Will you create hundreds or thousands of controller actions? Of course not, then how can we fix it?

In the MVC Framework, the controller class includes a method, HandleUnknownAction(), that executes whenever we attempt to invoke an action (or when we request a view that has no matching action method) on a controller that does not exist.


Now we are taking advantage of the HandleUnknownAction() method to render views even when a corresponding controller method does not exist.

In the image above you can see we don't have Post5.cshtml, so when I tried to access the Post5.cshtml view, it shows the following error.


To fix this issue, we can use a simple try-catch block and redirect the user on a PageNotFound view; here's how.


 



ASP.NET MVC 6 Hosting - HostForLIFE :: Upload Large Files To MVC / WebAPI Using Partitioning

clock February 8, 2021 09:26 by author Peter

Sending large files to an MVC/Web-API Server can be problematic. This article is about an alternative. The approach used is to break a large file up into small chunks, upload them, then merge them back together on the Server via file transfer by partitioning. The article shows how to send files to an MVC Server from both a webpage using JavaScript, and a Web-form httpClient, and can be implemented using either MVC or Web API.

In my experience, the larger the file you need to upload to a website/API, the bigger the potential problems you encounter. Even when you put the right settings in place, adjust your web.config, make certain you use the right multiplier for maxRequestLength and maxAllowedContentLength and of course don't forget about executionTimeout (eek!), things can still go wrong. Connections can fail when the file is *almost* transferred, servers unexpectedly (Murphy's law) run out of space, etc., the list goes on. The diagram below demonstrates the basic concept discussed in this article.

Background
The concept for this solution is very simple. The attached code works (I have it started in production), and can be improved by you in many ways. For example, for the purposes of this article the original large file is broken into app. 1mb chunks, and uploaded to the server sequentially, one chunk at a time. This could, for example, be made more efficient by threading, and sending chunks in parallel. It could also be made more robust by adding fault tolerance, auto-resume into a rest-api architecture etc. I leave you to implement these features yourself if you need them.

The code consists of two parts - the initial file-split/partitioning into chunks, and the final merge of the chunks back into the original file. I will demonstrate the file-split using both C# in a web-form, and JavaScript, and the file-merge using C# server-side.

File split
The concept of splitting a file is very basic. We transverse the file in a binary stream, from position zero, up to the last byte in the file, copying out chunks of binary data along the way and transferring these. Generally we set an arbitrary (or carefully thought out!) chunk size to extract, and use this as the amount of data to take at a time. Anything left over at the end is the final chunk.

In the example below, a chunk size of 128b is set. For the file shown, this gives us 3 x 128b chunks, and 1 x 32b. In this example there are four file chunks resulting from the split and to transfer to the server.

C# File Split
The accompanying demo "WinFileUpload" is a simple Windows forms application. Its sole function is to demonstrate splitting a sample large file (50 MB) in C#, and using a HTTPClient to post the file to a web-server (in this case, an MVC Server).

For this C# example, I have a class called Utils  that takes some input variables such as maximum file chunk size, temporary folder location, and the name of the file to split. To split the file into chunks, we call the method "SplitFile". SplitFile works its way through the input file and breaks it into separate file chunks. We then upload each file chunk it using "UploadFile".
Utils ut = new Utils();  
ut.FileName = "hs-2004-15-b-full_tif.bmp"; // hard coded for demo  
ut.TempFolder = Path.Combine(CurrentFolder, "Temp");  
ut.MaxFileSizeMB = 1;  
ut.SplitFile();  

foreach (string File in ut.FileParts)  
{  
UploadFile(File);  
}  
MessageBox.Show("Upload complete!");  


The file upload method takes an input file-name, and uses a HTTPClient to upload the file. Note the fact that we are sending MultiPartFormData to carry the payload.
public bool UploadFile(string FileName)  
{  
bool rslt = false;  
using (var client = new HttpClient())  
{  
using (var content = new MultipartFormDataContent())  
{  
 var fileContent = new   ByteArrayContent(System.IO.File.ReadAllBytes(FileName));  
 fileContent.Headers.ContentDisposition = new  
     ContentDispositionHeaderValue("attachment")  
       {  
        FileName = Path.GetFileName(FileName)  
       };  
 content.Add(fileContent);  

var requestUri = "http://localhost:8170/Home/UploadFile/";  
    try  
    {  
        var result = client.PostAsync(requestUri, content).Result;  
        rslt = true;  
    }  
    catch (Exception ex)  
    {  
        // log error  
        rslt = false;  
    }  
}  
}  
return rslt;  
}  


So, that's the supporting code out of the way. One of the critical things to be aware of next is the file naming convention that is being used. It consists of the original file-name, plus a code-parsable tail "_part." that will be used server-side to merge the different file chunks back into a single contiguous file again. This is simply the convention I put together - you can change it to your own requirements, just be sure you are consistent with it.

The convention for this example is,
Name = original name + ".part_N.X" (N = file part number, X = total files).

Here is an example of a picture file split into three parts.
MyPictureFile.jpg.part_1.3
MyPictureFile.jpg.part_2.3
MyPictureFile.jpg.part_3.3

It doesn't matter what order the file chunks are sent to the Server. The important thing is that some convention, like the above is used, so that the Server knows (a) what file part it is dealing with and (b) when all parts have been received and can be merged back into one large original file again.

Next, here is the meat of the C# code that scans the file, creating multiple chunk files ready to transfer.
public bool SplitFile()  
{  
bool rslt = false;  
string BaseFileName = Path.GetFileName(FileName);  
// set the size of file chunk we are going to split into  
int BufferChunkSize = MaxFileSizeMB * (1024 * 1024);  
// set a buffer size and an array to store the buffer data as we read it  
const int READBUFFER_SIZE = 1024;  
byte[] FSBuffer = new byte[READBUFFER_SIZE];  
// open the file to read it into chunks  
using (FileStream FS = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read))  
{  
// calculate the number of files that will be created  
int TotalFileParts = 0;  
if (FS.Length < BufferChunkSize)  
{  
    TotalFileParts = 1;  
}  
else  
{  
    float PreciseFileParts = ((float)FS.Length / (float)BufferChunkSize);  
    TotalFileParts = (int)Math.Ceiling(PreciseFileParts);  
}  

int FilePartCount = 0;  
// scan through the file, and each time we get enough data to fill a chunk, write out that file  
while (FS.Position < FS.Length)  
{  
    string FilePartName = String.Format("{0}.part_{1}.{2}",  
    BaseFileName, (FilePartCount + 1).ToString(), TotalFileParts.ToString());  
    FilePartName = Path.Combine(TempFolder, FilePartName);  
    FileParts.Add(FilePartName);  
    using (FileStream FilePart = new FileStream(FilePartName, FileMode.Create))  
    {  
        int bytesRemaining = BufferChunkSize;  
        int bytesRead = 0;  
        while (bytesRemaining > 0 && (bytesRead = FS.Read(FSBuffer, 0,  
         Math.Min(bytesRemaining, READBUFFER_SIZE))) > 0)  
        {  
            FilePart.Write(FSBuffer, 0, bytesRead);  
            bytesRemaining -= bytesRead;  
        }  
    }  
  // file written, loop for next chunk  
  FilePartCount++;  
}  

}  
return rslt;  
}  


That's it for the C# client-side - we will see the result and how to handle things server-side later in the article. Next, let's look at how to do the same thing in Javascript, from a web-browser.
JavaScript File Split

NB - The JavaScript code, and the C# Merge code are contained in the attached demo file "MVCServer"

In our browser, we have an input control of type "file", and a button to call a method that initiates the file-split and data transfer.
<input type="file" id="uploadFile" name="file" />  <a class="btn btn-primary" href="#" id="btnUpload">Upload file</a>  

On document ready, we bind to the click event of the button to call the main method.
$(document).ready(function () {  
$('#btnUpload').click(function () {  
UploadFile($('#uploadFile')[0].files);  
}  
)  
});  


Our UploadFile method does the work of splitting the file into chunks, and as in our C# example, passing the chunks off to another method for transfer. The main difference here is that in C#, we created individual files, in our JavaScript example, we are taking the chunks from an array instead.  
function UploadFile(TargetFile)  
{  
// create array to store the buffer chunks  
var FileChunk = [];  
// the file object itself that we will work with  
var file = TargetFile[0];  
// set up other initial vars  
var MaxFileSizeMB = 1;  
var BufferChunkSize = MaxFileSizeMB * (1024 * 1024);  
var ReadBuffer_Size = 1024;  
var FileStreamPos = 0;  
// set the initial chunk length  
var EndPos = BufferChunkSize;  
var Size = file.size;  

// add to the FileChunk array until we get to the end of the file  
while (FileStreamPos < Size)  
{  
// "slice" the file from the starting position/offset, to  the required length  
FileChunk.push(file.slice(FileStreamPos, EndPos));  
FileStreamPos = EndPos; // jump by the amount read  
EndPos = FileStreamPos + BufferChunkSize; // set next chunk length  
}  
// get total number of "files" we will be sending  
var TotalParts = FileChunk.length;  
var PartCount = 0;  
// loop through, pulling the first item from the array each time and sending it  
while (chunk = FileChunk.shift())  
{  
PartCount++;  
// file name convention  
var FilePartName = file.name + ".part_" + PartCount + "." + TotalParts;  
// send the file  
UploadFileChunk(chunk, FilePartName);  
}  
}  


The UploadFileChunk takes the part of the file handed by the previous method, and posts it to the Server in a similar manner to the C# example.
function UploadFileChunk(Chunk, FileName)  
{  
var FD = new FormData();  
FD.append('file', Chunk, FileName);  
$.ajax({  
type: "POST",  
url: 'http://localhost:8170/Home/UploadFile/',  
contentType: false,  
processData: false,  
data: FD  
});  
}  


File merge
NB - The JavaScript code, and the C# Merge code are contained in the attached demo file "MVCServer"

Over on the Server, be that MVC or Web-API, we receive the individual file chunks and need to merge them back together again into the original file.

The first thing we do is put a standard POST handler in place to receive the file chunks being posted up to the Server. This code takes the input stream, and saves it to a temp folder using the file-name created by the client (C# or JavaScript). Once the file is saved, the code then calls the "MergeFile" method which checks if it has enough file chunks available yet to merge the file together. Note that this is simply the method I have used for this article. You may decide to handle the merge trigger differently, for example, running a job on a timer every few minutes, passing off to another process, etc. It should be changed depending on your own required implementation.

[HttpPost]  
public HttpResponseMessage UploadFile()  
{  
foreach (string file in Request.Files)  
{  
var FileDataContent = Request.Files[file];  
if (FileDataContent != null && FileDataContent.ContentLength > 0)  
{  
    // take the input stream, and save it to a temp folder using  
    // the original file.part name posted  
    var stream = FileDataContent.InputStream;  
    var fileName = Path.GetFileName(FileDataContent.FileName);  
    var UploadPath = Server.MapPath("~/App_Data/uploads");  
    Directory.CreateDirectory(UploadPath);  
    string path = Path.Combine(UploadPath, fileName);  
    try  
    {  
        if (System.IO.File.Exists(path))  
            System.IO.File.Delete(path);  
        using (var fileStream = System.IO.File.Create(path))  
        {  
            stream.CopyTo(fileStream);  
        }  
        // Once the file part is saved, see if we have enough to merge it  
        Shared.Utils UT = new Shared.Utils();  
        UT.MergeFile(path);  
    }  
    catch (IOException ex)  
    {  
       // handle  
    }  
}  
}  
return new HttpResponseMessage()  
{  
StatusCode = System.Net.HttpStatusCode.OK,  
Content = new StringContent("File uploaded.")  
};  
}  


Each time we call the MergeFile method, it first checks to see if we have all of the file chunk parts required to merge the original file back together again. It determines this by parsing the file-names. If all files are present, the method sorts them into the correct order, and then appends one to another until the original file that was split, is back together again.
/// <summary>  
/// original name + ".part_N.X" (N = file part number, X = total files)  
/// Objective = enumerate files in folder, look for all matching parts of  
/// split file. If found, merge and return true.  
/// </summary>  
/// <param name="FileName"></param>  
/// <returns></returns>  
public bool MergeFile(string FileName)  
{  
bool rslt = false;  
// parse out the different tokens from the filename according to the convention  
string partToken = ".part_";  
string baseFileName = FileName.Substring(0, FileName.IndexOf(partToken));  
string trailingTokens = FileName.Substring(FileName.IndexOf(partToken) + partToken.Length);  
int FileIndex = 0;  
int FileCount = 0;  
int.TryParse(trailingTokens.Substring(0, trailingTokens.IndexOf(".")), out FileIndex);  
int.TryParse(trailingTokens.Substring(trailingTokens.IndexOf(".") + 1), out FileCount);  
// get a list of all file parts in the temp folder  
string Searchpattern = Path.GetFileName(baseFileName) + partToken + "*";  
string[] FilesList = Directory.GetFiles(Path.GetDirectoryName(FileName), Searchpattern);  
//  merge .. improvement would be to confirm individual parts are there / correctly in  
// sequence, a security check would also be important  
// only proceed if we have received all the file chunks  
if (FilesList.Count() == FileCount)  
{  
// use a singleton to stop overlapping processes  
if (!MergeFileManager.Instance.InUse(baseFileName))  
{  
    MergeFileManager.Instance.AddFile(baseFileName);  
    if (File.Exists(baseFileName))  
        File.Delete(baseFileName);  
    // add each file located to a list so we can get them into  
    // the correct order for rebuilding the file  
    List<SortedFile> MergeList = new List<SortedFile>();  
    foreach (string File in FilesList)  
    {  
        SortedFile sFile = new SortedFile();  
        sFile.FileName = File;  
        baseFileName = File.Substring(0, File.IndexOf(partToken));  
        trailingTokens = File.Substring(File.IndexOf(partToken) + partToken.Length);  
        int.TryParse(trailingTokens.  
           Substring(0, trailingTokens.IndexOf(".")), out FileIndex);  
        sFile.FileOrder = FileIndex;  
        MergeList.Add(sFile);  
    }  
    // sort by the file-part number to ensure we merge back in the correct order  
    var MergeOrder = MergeList.OrderBy(s => s.FileOrder).ToList();  
    using (FileStream FS = new FileStream(baseFileName, FileMode.Create))  
    {  
        // merge each file chunk back into one contiguous file stream  
        foreach (var chunk in MergeOrder)  
        {  
            try  
            {  
                using (FileStream fileChunk =  
                   new FileStream(chunk.FileName, FileMode.Open))  
                {  
                    fileChunk.CopyTo(FS);  
                }  
            }  
            catch (IOException ex)  
            {  
                // handle  
            }  
        }  
    }  
    rslt = true;  
    // unlock the file from singleton  
    MergeFileManager.Instance.RemoveFile(baseFileName);  
}  
}  
return rslt;  
}  


Using the file split on the client-side, and file-merge on the server-side, we now have a very workable solution for uploading large files in a more secure manner than simply sending up in one large block of data.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: HTTP Error 404.0 0 Not Found in MVC

clock January 29, 2021 08:32 by author Peter

The Resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I saw this error today while working on a MVC Web Project, this is a common error we get while running websites and performing any CRUD (Create, Read, Update, Delete) operation. The Stackoverflow forum is full of such queries so I decided to describe the fix here. You might not find it useful for your case but I think the majority of requests can be satisfied.

 
Let me show you an error page image here:


Look at the URL in the above image. The URL is requesting a view/page to edit the record but unfortunately the page is not found. Actually the page/view is already there but the problem is, we are not supplying the correct ID or say index to edit.
In other words we need an URL something like http://localhost:25349/demo/Edit/1 to edit the first record and http://localhost:25349/demo/Edit/2 to edit the second record. Yet in the preceding image we are not supplying the ID.
 
Let's fix it. Open the "Index" view of the "demo" controller and look at the existing code:


Oh! there is a comment instead of the ID parameter, so once you change it, such as in the following:
    <td>  
        @Html.ActionLink("Edit", "Edit", new { id=item.SM_UID }) |  
        @Html.ActionLink("Details", "Details", new { id=item.SM_UID }) |  
        @Html.ActionLink("Delete", "Delete", new { id=item.SM_UID })  
    </td>  


Your application will work fine.



About HostForLIFE

HostForLIFE 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 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Tag cloud

Sign in