I have a ASP.Net web project that was done in VS2010 and now I want to publish it with VS2015. Then, the compiler complained that there are many compilation errors such as CS0117 (method or extension method not found) and CS0246 (type or namespace not found). After hours of research on the web, still cannot find any solution to have VS2015 to publish the ASP.net 3.5 project.
Finally, I decided not to use VS2015 to publish the old project. Instead using command line to publish it even though the steps are a bit lengthy.
Here is the steps:
1. Run VS2015 and open the ASP.net 3.5 web project.
2. Choose Release mode.
3. Choose Rebuild Solution.
4. Upon rebuild done, copy the entire website folder into "d:\manual-compile" folder (or whichever folder that you like).
5. Then, run the following command in command prompt:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v /website1 -p d:\manual-compile\website1 -u -fixednames d:\manual-compile\website1-compiled
Wait for a while and you will see the precompiled version of ASP.net appeared in "d:\manual-compile\website1-compiled" folder. There you go.
Tuesday, April 25, 2017
Creating Asp.net Core/MVC from a miminal Asp.net Core project template
Creating a new project from the Web Application template is troublesome in deleting the unwanted files. Let's try to create a minimal Asp.net Core project (not an Empty project).
First thing, you have to create a Web API Asp.net Core project and then follow the following steps to complete the project.
1. Add HomeController class into Controllers folder and the code is shown as follow:
public class HomeController : Controller
{
// returns the default page.
public IActionResult Index()
{
return View();
}
//returns the contact us page.
public IActionResult ContactUs()
{
return View();
}
}
2. Modify the Configure() in Startup.cs
app.UseMvc(route =>
{
// adding a new route for http://localhost:xxx/contactUs
route.MapRoute(name: "contact_us",
template: "contactUs",
defaults: new { controller = "Home", action = "ContactUs" });
// if the path in the url is blank, call HomeController.
route.MapRoute(name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
3. Add Index.cshtml and ContactUs.cshtml into Views\Home folder.
In the Index page, it looks like this:
@{
ViewData["Title"] = "Home";
}
<h1>MY APP</h1>
<h2>This is Home page</h2>
<a href="ContactUs">Jump to Contact Us page</a>
In the ContactUs page, it looks like this:
@{
ViewData["Title"] = "Contact Us";
}
<h1>MY APP</h1>
<h2>This is Contact Us page</h2>
<a href="">Jump to Home page</a>
4. Add _Layout.cshtml into Views\Shared folder and the content looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - My App </title>
<environment names="Development">
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© 2016 - My App</p>
</footer>
</div>
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("scripts", required: false)
</body>
</html>
5. Add _ViewStart.cshtml into Views folder with the following content. Now, the Asp.net will merge all the views with this "_Layout.cshtml".
@{
Layout = "_Layout";
}
6. Add site.css into wwwroot\css folder with the following contents:
body {
font-family:Tahoma;
font-size: 12pt;
color: #757575;
margin: 0;
}
7. Press F5 to run your website.
8. You might notice that the site.css was not loaded. Let's continue by calling up the NuGet Package Manager. Search the "Microsoft.AspNetCore.StaticFiles" and include it into your project.
9. In Configure() in the Startup.cs file, add the following code before the app.UseMvc()
app.UseStaticFiles();
10. Press F5 to run your website and the css file will be loaded into the browser.
First thing, you have to create a Web API Asp.net Core project and then follow the following steps to complete the project.
1. Add HomeController class into Controllers folder and the code is shown as follow:
public class HomeController : Controller
{
// returns the default page.
public IActionResult Index()
{
return View();
}
//returns the contact us page.
public IActionResult ContactUs()
{
return View();
}
}
2. Modify the Configure() in Startup.cs
app.UseMvc(route =>
{
// adding a new route for http://localhost:xxx/contactUs
route.MapRoute(name: "contact_us",
template: "contactUs",
defaults: new { controller = "Home", action = "ContactUs" });
// if the path in the url is blank, call HomeController.
route.MapRoute(name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
3. Add Index.cshtml and ContactUs.cshtml into Views\Home folder.
In the Index page, it looks like this:
@{
ViewData["Title"] = "Home";
}
<h1>MY APP</h1>
<h2>This is Home page</h2>
<a href="ContactUs">Jump to Contact Us page</a>
In the ContactUs page, it looks like this:
@{
ViewData["Title"] = "Contact Us";
}
<h1>MY APP</h1>
<h2>This is Contact Us page</h2>
<a href="">Jump to Home page</a>
4. Add _Layout.cshtml into Views\Shared folder and the content looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - My App </title>
<environment names="Development">
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© 2016 - My App</p>
</footer>
</div>
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("scripts", required: false)
</body>
</html>
5. Add _ViewStart.cshtml into Views folder with the following content. Now, the Asp.net will merge all the views with this "_Layout.cshtml".
@{
Layout = "_Layout";
}
6. Add site.css into wwwroot\css folder with the following contents:
body {
font-family:Tahoma;
font-size: 12pt;
color: #757575;
margin: 0;
}
7. Press F5 to run your website.
8. You might notice that the site.css was not loaded. Let's continue by calling up the NuGet Package Manager. Search the "Microsoft.AspNetCore.StaticFiles" and include it into your project.
9. In Configure() in the Startup.cs file, add the following code before the app.UseMvc()
app.UseStaticFiles();
10. Press F5 to run your website and the css file will be loaded into the browser.
Tuesday, February 7, 2017
Something about Asp.net Core/MVC
This is something that you should know about Asp.net Core:
1) To create a link that points to the correct virtual directory, you can use the following:
<a href="~/api/mybook">See my books</a>
OR
var s = " root is= " + Url.Content("~/");
2) To expose the controller class to the desired URL path, you have to add the "Route" class attribute. In the following case, "MyBook" service is accessible through "http://localhost:1234/api/MyBook" while "Values" is accessible through "http://localhost:1234/values/"
[Route("api/[controller]")
public class MyBookController : Controller {..}
[Route("[controller]")]
public class ValuesController : Controller {..}
In Startup.cs:
app.UseMvc(routes =>
{
// set the default route
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
});
3) To publish the static files, you must called out the NuGet and then add the reference to this library "Microsoft.AspNetCore.StaticFiles". After that, you will be able to use the code in Startup.Configure() proc:
app.UseStaticFiles();
4) To setup the application in IIS, first, you need to add an application pool with "No Managed Code" option. Then, publish a new virtual application that points to the output path. For example,
src\WebApplication1\bin\Release\PublishOutput
5)
5.1) To return the HTML content, you must return the View() and the Index.cshtml file must be stored in the Views\MyBook folder.
[HttpGet]
public ActionResult Index()
{
var l = this._my_book.GetList();
return View(l);
}
5.2) To return the value as plain content type:
[HttpGet("{id}")]
public string Get(int id)
{
return "value=" + id.ToString();
}
5.3) To return the data in JSON format:
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(string id)
{
var item = TodoItems.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
6) Receiving the dynamic JObject param:
[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]Newtonsoft.Json.Linq.JObject value)
{
//...
}
7)
protected bool CheckStatus304(DateTime lastModified)
{
//http://weblogs.asp.net/jeff/304-your-images-from-a-database
if (!String.IsNullOrEmpty(Request.Headers["If-Modified-Since"]))
{
CultureInfo provider = CultureInfo.InvariantCulture;
var lastMod = DateTime.ParseExact(Request.Headers["If-Modified-Since"], "r", provider).ToLocalTime();
if (lastMod == lastModified.AddMilliseconds(-lastModified.Millisecond))
{
Response.StatusCode = 304;
//Response.StatusDescription = "Not Modified";
return true;
}
}
//Response.Cache.SetCacheability(HttpCacheability.Public);
//Response.Cache.SetLastModified(lastModified);
//use this instead of the above:
//string timeString = lastModified.ToUniversalTime().ToString("R");
//Response.Headers.Append("Last-Modified", timeString);
return false;
}
1) To create a link that points to the correct virtual directory, you can use the following:
<a href="~/api/mybook">See my books</a>
OR
var s = " root is= " + Url.Content("~/");
2) To expose the controller class to the desired URL path, you have to add the "Route" class attribute. In the following case, "MyBook" service is accessible through "http://localhost:1234/api/MyBook" while "Values" is accessible through "http://localhost:1234/values/"
[Route("api/[controller]")
public class MyBookController : Controller {..}
[Route("[controller]")]
public class ValuesController : Controller {..}
In Startup.cs:
app.UseMvc(routes =>
{
// set the default route
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
});
3) To publish the static files, you must called out the NuGet and then add the reference to this library "Microsoft.AspNetCore.StaticFiles". After that, you will be able to use the code in Startup.Configure() proc:
app.UseStaticFiles();
4) To setup the application in IIS, first, you need to add an application pool with "No Managed Code" option. Then, publish a new virtual application that points to the output path. For example,
src\WebApplication1\bin\Release\PublishOutput
5)
5.1) To return the HTML content, you must return the View() and the Index.cshtml file must be stored in the Views\MyBook folder.
[HttpGet]
public ActionResult Index()
{
var l = this._my_book.GetList();
return View(l);
}
5.2) To return the value as plain content type:
[HttpGet("{id}")]
public string Get(int id)
{
return "value=" + id.ToString();
}
5.3) To return the data in JSON format:
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(string id)
{
var item = TodoItems.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
6) Receiving the dynamic JObject param:
[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]Newtonsoft.Json.Linq.JObject value)
{
//...
}
7)
protected bool CheckStatus304(DateTime lastModified)
{
//http://weblogs.asp.net/jeff/304-your-images-from-a-database
if (!String.IsNullOrEmpty(Request.Headers["If-Modified-Since"]))
{
CultureInfo provider = CultureInfo.InvariantCulture;
var lastMod = DateTime.ParseExact(Request.Headers["If-Modified-Since"], "r", provider).ToLocalTime();
if (lastMod == lastModified.AddMilliseconds(-lastModified.Millisecond))
{
Response.StatusCode = 304;
//Response.StatusDescription = "Not Modified";
return true;
}
}
//Response.Cache.SetCacheability(HttpCacheability.Public);
//Response.Cache.SetLastModified(lastModified);
//use this instead of the above:
//string timeString = lastModified.ToUniversalTime().ToString("R");
//Response.Headers.Append("Last-Modified", timeString);
return false;
}
Thursday, January 19, 2017
Setting up the delete permission in IIS
The following content was copied from this reference:
http://stackoverflow.com/questions/7334216/iis7-permissions-overview-applicationpoolidentity
ApplicationPoolIdentity is actually the best practice to use in IIS7. It is a dynamically created, unprivelaged account. To add file system security for a particular application pool see IIS.net's "Application Pool Identities". The quick version:
If you application pool is named "DefaultAppPool" (just replace this text below if it is named differently)
Open Windows Explorer
Select a file or directory.
Right click the file and select "Properties"
Select the "Security" tab
Click the "Edit" and then "Add" button
Click the "Locations" button and make sure you select the local machine. (Not the Windows domain if the server belongs to one.)
Enter "IIS AppPool\DefaultAppPool" in the "Enter the object names to select:" text box. (Don't forget to change "DefaultAppPool" here to whatever you named your application pool.)
Click the "Check Names" button and click "OK".
http://stackoverflow.com/questions/7334216/iis7-permissions-overview-applicationpoolidentity
ApplicationPoolIdentity is actually the best practice to use in IIS7. It is a dynamically created, unprivelaged account. To add file system security for a particular application pool see IIS.net's "Application Pool Identities". The quick version:
If you application pool is named "DefaultAppPool" (just replace this text below if it is named differently)
Open Windows Explorer
Select a file or directory.
Right click the file and select "Properties"
Select the "Security" tab
Click the "Edit" and then "Add" button
Click the "Locations" button and make sure you select the local machine. (Not the Windows domain if the server belongs to one.)
Enter "IIS AppPool\DefaultAppPool" in the "Enter the object names to select:" text box. (Don't forget to change "DefaultAppPool" here to whatever you named your application pool.)
Click the "Check Names" button and click "OK".
Tuesday, October 4, 2016
Using partial HTML UI + ASHX to speed up page loading
Just to share with everyone that I developed many LOB app (line of business application) and I'm still developing new LOB for my clients. LOB is very different from blog engine, corporate websites and static websites. In LOB, we can happily ignore the contents to be "readable" by SEO because some of the contents were loaded by AJAX.
As per my last blog dated 26th-June-2016, I mentioned the new strategy: JQuery + AJAX + partial HTML UI. Now, the question is how is partial HTML UI that can help out is speeding up the page loading? The answer is simple, we need to rely on the browser cache by checking the "If-Modified-Since" flag in the request header. Then, responding either status code 304 (resource has not been modified) or returning the partial HTML to the browser.
You will find tons of references if you are searching for "asp.net If-Modified-Since". Below is one of the reference that I found:
http://madskristensen.net/post/use-if-modified-since-header-in-aspnet
The down side of this strategy is that the user will feel a bit slower on the first request to load the full page. But, the subsequent page loading or if the user is requesting for the same page, then, the time taken will be shorter. For example, we want to develop a page for user to key in the sales invoice and it allows the user from choosing the item from the list. The sales invoice is stored in a HTML file (not ASPX) and the item list HTML design is stored in another HTML file (where this item list will be reused by supplier invoice).
One of the advantage using this strategy is that it allows all these partial HTML file to be hosted in CDN (Content Delivery Network). Then, the whole LOB app will be loaded faster than using only one ASPX which could be crazily huge and hard to reuse some of the HTML design.
Note: "partial HTML UI" can be refer as "template" and it does not contains the HEAD and BODY tags. It just contains some DIV-s which eases the web designer to design and test in the browser. You don't need a programmer to start full coding but just some simple JQuery and AJAX to complete the demo.
As per my last blog dated 26th-June-2016, I mentioned the new strategy: JQuery + AJAX + partial HTML UI. Now, the question is how is partial HTML UI that can help out is speeding up the page loading? The answer is simple, we need to rely on the browser cache by checking the "If-Modified-Since" flag in the request header. Then, responding either status code 304 (resource has not been modified) or returning the partial HTML to the browser.
You will find tons of references if you are searching for "asp.net If-Modified-Since". Below is one of the reference that I found:
http://madskristensen.net/post/use-if-modified-since-header-in-aspnet
The down side of this strategy is that the user will feel a bit slower on the first request to load the full page. But, the subsequent page loading or if the user is requesting for the same page, then, the time taken will be shorter. For example, we want to develop a page for user to key in the sales invoice and it allows the user from choosing the item from the list. The sales invoice is stored in a HTML file (not ASPX) and the item list HTML design is stored in another HTML file (where this item list will be reused by supplier invoice).
One of the advantage using this strategy is that it allows all these partial HTML file to be hosted in CDN (Content Delivery Network). Then, the whole LOB app will be loaded faster than using only one ASPX which could be crazily huge and hard to reuse some of the HTML design.
Note: "partial HTML UI" can be refer as "template" and it does not contains the HEAD and BODY tags. It just contains some DIV-s which eases the web designer to design and test in the browser. You don't need a programmer to start full coding but just some simple JQuery and AJAX to complete the demo.
Labels:
.Net,
AJAX,
ASHX,
ASP.NET,
C#,
Enhancement,
Optimization,
Reusable,
System Design,
System Development
Tuesday, August 2, 2016
Color settings in VS2015
After working years and years on computer, it's time to adjust the color in VS2015. This can be done by selecting Options from Tools menu. Then, look for "Fonts and Colors" under Environment and you may start editing the colors for "Text Edit":
ColorThemeEditor.vsix - to change the VS color scheme.
https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.VisualStudio2015ColorThemeEditor
VisualCommander_263.vsix - to automate some text to be injected and binding the command to shortcut key.
https://marketplace.visualstudio.com/items?itemName=SergeyVlasov.VisualCommander
Sample code to inject current date, time & my name to the text editor:
Sub Run(DTE As EnvDTE80.DTE2, package As Microsoft.VisualStudio.Shell.Package) Implements VisualCommanderExt.ICommand.Run
Dim textSelection As EnvDTE.TextSelection
textSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)
textSelection.Text = "//" + System.DateTime.Now.ToString("d.MMM.yy") + ", myName-"
End Sub
Don't forget to customize the "keyboard" and bind it to any shortcut that you like. As for myself, I reset CTRL+[0 to 9] and bind it with my command.
- Plan text - adjust the background color to RGB(228, 228, 228)
- Brace Matching RGB(0, 185, 0)
- Brace Matching (Rectangle) RGB(0, 128, 0)
- Hightlighted Definition RGB(185, 194, 154)
- Hightlighted Reference RGB(249, 182, 100)
- Preprocessor keyword
- User Types - xxx
ColorThemeEditor.vsix - to change the VS color scheme.
https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.VisualStudio2015ColorThemeEditor
VisualCommander_263.vsix - to automate some text to be injected and binding the command to shortcut key.
https://marketplace.visualstudio.com/items?itemName=SergeyVlasov.VisualCommander
Sample code to inject current date, time & my name to the text editor:
Sub Run(DTE As EnvDTE80.DTE2, package As Microsoft.VisualStudio.Shell.Package) Implements VisualCommanderExt.ICommand.Run
Dim textSelection As EnvDTE.TextSelection
textSelection = CType(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)
textSelection.Text = "//" + System.DateTime.Now.ToString("d.MMM.yy") + ", myName-"
End Sub
Don't forget to customize the "keyboard" and bind it to any shortcut that you like. As for myself, I reset CTRL+[0 to 9] and bind it with my command.
Sunday, June 26, 2016
System design with ASHX web services (JQuery + AJAX + partial HTML UI)
Recently, we are working on a few new systems with ASP.NET. In the past, we are using Page (ASPX) + ScriptManager and we are facing some limitation in the system design which includes the following:
To solve this problem, here is the list of frequent use "web service" to be implemented with Handler (ASHX):
<system.web>
<urlMappings>
<add url="~/q" mappedUrl="~/myWebService/q.ashx"/>
</urlMappings>
</system.web>
The design these web services:
- The system does not allow the user to add a new "item" into the drop down list on the fly.
- The drop down list contains a few hundred items and we need to incorporate the 'search' functionality or paging to avoid all items to be loaded in one shot.
- The data submitted to server failed to meet the validation process and causing the entire page sent back to the client (which travel from client to the server and then back to the client).
- We must use JQuery + AJAX + partial HTML UI design so that it allows the user from adding "item" to the drop down list on the fly. The partial HTML UI will appear on the screen as a popup for user adding new item. After the user has submitted the new item to the server, validated OK and it will be added to the drop down list on the fly (with JQuery) without reloading the page or navigating to another page.
- The drop down list that contains lots of item will be replace by a textbox. Upon the user clicking on this textbox, the items will be loaded from the server (with AJAX calls) and then display in the popup (with JQuery + partial HTML UI). To improve the user's experience, you may consider the auto-complete feature upon the user typing the text or divide the data using the paging concept.
- We must do more AJAX calls for submitting the user input to be validated by the system. In case of any failure such as validation failed, the server should returns the error message only. This avoids the entire page to be re-created in the server and then send to the browser.
To solve this problem, here is the list of frequent use "web service" to be implemented with Handler (ASHX):
- ~/q - this web service handles the "query" that includes CRUD (create, return, update & delete) processes, daily process, ad-hoc process and all other business processes. The report request is another area which you may consider to put into this service.
- ~/t - this web service returns the "HTML template" (partial HTML UI design) to be injected to the current web page. By creating the partial HTML UI file, it allows the designer to work on the layout without have to go through all the JQuery + the DOM element generation (i.e., low level stuffs). Modifying the DOM elements using JQquery is very time consuming and it requires a more expensive Javascript programmer. But, we have done it with a cheaper costing. The nice partial HTML UI has been done by the designer and the programmer requires to populate the JSON data into the appropriate placeholder.
- ~/f - this web service handles all the file services that include upload, download/view. For example, when the user calls out the "contact list", it shows the profile photo of the contact. This profile photo IMG SRC is "~/f?contact_id=124567" where "contact_id" is the primary key value of the contact. It does not point to any physical file name. The "f" service will do all the necessary at the server side and returns the binary of the photo (an image file).
<system.web>
<urlMappings>
<add url="~/q" mappedUrl="~/myWebService/q.ashx"/>
</urlMappings>
</system.web>
The design these web services:
- Client is making a request to the web service:
- "code" - the command code, object type or process code to be executed.
- "action" - this includes CRUD and other actions (such as run daily job, run hour job).
- "query parameters" - the query parameters are wrapped into a JSON object. For example, the client is requesting the customers who is owing more than $10,000 for more than 90 days.
- Responding to the client:
- "msg" - the message to the client. "ok" to indicate the query has successfully executed. Otherwise, it contains the error message.
- "list" - the list of JSON formatted data requested by the client. This information is optional.
Labels:
.Net,
AJAX,
ASHX,
ASP.NET,
C#,
Enhancement,
JQuery,
Optimization,
System Design
Subscribe to:
Posts (Atom)