|
I've been pondering the notion of mixing Angular with .Net MVC as well for about 3 weeks now.
Noticed how I wrote Angular and not AngularJS? AngularJS was the first version, then they changed the name to just Angular.
I just added Angular 5 to my .Net Core 2.1 project, and will write some Angular stuff next week. So I'm moving forward with it and decided to adopt it.
Why?
I questioned why so many software recruiters are looking for the Senior .Net Core 2 and Angular guy, and thought why? There both MVC except one is client and one is server. So I started searching the interwebs for the answer and this is what I found.
Weather.com
At first, I found weather.com, that uses Angular to display the weather for your city for that day. A single page app in which you can move to the next day, or a week, 10 day forecast, and the home page "Wall" of weather related topics. So I get it.
TV Guide
The I went to TV Guide, and saw similiar technology being used for TV Listings. You can hit next and get the listings for the next hour. Makes sense to me here as well.
Navigation
After that I realized that it could be used for menu's and navigation as well. Being able to take a Bootstrap dropdown menu and use Angular to populate departments, categories instead of the menu being static. Or create flyouts ads, and grab an ad using Angular and then animate it.
My thoughts
So MVC has the controller and Models, then you create a limited view, and finish it off with Angular. When I look at .Net Core 2.1, I can see how you can build a limited version of core with a couple View pages and serve up Angular or ReactJS pages instead. I'm looking at the Angular Demo now, and that would be too hard core for me to start with. I choose to use NPM and distribute it with Gulp and bundle it, and will try building another Angular page within a View.
Summary
Well that's as far as I have gotten on the subject. But once again it's another move towards shifting server CPU loads and bandwidth back to the client and use their CPU power and electricity to generate a page. Servers can just send Json formatted data. I'll find out in time if it's worth it or not, plus I have zero debate points to argue in favor of it.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
jkirkerx wrote: notion of mixing Angular with .Net MVC
You probably can mix Angular and ASP.NET MVC, but if you are aiming for SPA, I would suggest to just stick to Angular as your front-end and use ASP.NET Web API /ASP.NET Core Web API as your back-end. Keep in mind that ASP.NET MVC is also front-end but generates pages from the server.
|
|
|
|
|
I'll get to that next week to see what you mean, and if my project build is correct.
But thanks for the heads up on that.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
what are some good open source projects written in angular 4+
with combination of ASP.NET MVC
=====================================================
The grass is always greener on the other side of the fence
|
|
|
|
|
|
This works in Fire Fox, but not in Chrome or Edge on Win 10.
In the Controller, when you login, I write a session value, and then redirect to a page.
On that page, I have a Controller Attribute called Admin Check, that checks for the session value.
I just can't get anything out of the HttpContext. I can on Fire Fox, but not chrome or Edge.
Not sure if it has something to do with HttpContext.Current, or the header, cookie.
I'm scratching my head on this one.
I ran some test, I get the session value in the IActionResult right after I write it.
Tried HttpContext.Items, same thing, so it must be related to HttpContext.
[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class AdminSecurityCheckAttribute : ActionFilterAttribute, IActionFilter
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var controller = filterContext.Controller as AdminController;
var HttpContext = controller.HttpContext;
if (HttpContext.Session.GetString("Admin_AccountName") != null)
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
I changed the cookie policy to none, renamed the Cookie and added IsEssential.
Not sure which one made it work, I'll have to isolate that.
It works on all browsers now, but I know it will come back and haunt me later.
<pre>
services.AddSession(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
options.Cookie.Name = ".AspNetCore.Session";
options.Cookie.SecurePolicy = CookieSecurePolicy.None;
options.Cookie.SameSite = SameSiteMode.Lax;
options.IdleTimeout = TimeSpan.FromMinutes(1440);
});
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
I have a sql table that I want to loop through and create html links
I currently have :-
DS = x.LoadBlueUploads(mynumber)
Dim dr As DataRow
dt = DS.Tables(0)
For Each dr In dt.Rows
Next dr
I've tried doing it as a label e.g. :-
Label1.Text += "<a href=""~/uploads/" + dr("FormUploadFileName").ToString() + """</a><br />"
But that doesn't seem to work, is there a better way ?
|
|
|
|
|
Try:
DS = x.LoadBlueUploads(mynumber)
Dim sb As New System.Text.StringBuilder()
For Each dr As DataRow In DS.Tables(0).Rows
sb.AppendFormat("<a href=""~/uploads/{0}"">{0}</a><br />", dr("FormUploadFileName"))
Next
Label1.Text = sb.ToString()
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
|
Hi,
I am using Kendo Dropdown list and Kendo Grid, when I select an item, in the dropdown, the Kendo grid should display the records for value of the selected item of the Kendo dropdown, when I change it, the records in the Grid also change. I am trying in the below way, not able to achieve, any help would be very helpful - thanks in advance.
@{
ViewBag.Title = "ListLookups";
//Layout = "~/Views/Shared/_LayoutFinal.cshtml";
}
<style>
.k-edit-form-container {
width: 500px;
}
</style>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="tab-content" id="dvtabs" style="padding-top:10px;">
<label class="col-md-4 control-label">Lookup</label>
@(Html.Kendo().DropDownList().Name("Lookup").OptionLabel("Select")
.DataTextField("Text")
.DataValueField("Value").HtmlAttributes(new { style = "width:280px;", @id = "drpLookup" })
.DataSource(dataSource => dataSource.Read(read => read.Action("GetListOfLookupTables", "Admin")))
.Events(e =>
{
e.Change("GetLookupTableValue");
})
<pre>
)
</div>
<div style="margin-top: 5px; padding-left:3%; padding-right:2%">
<div>
<div>
<h4>List of Contacts</h4>
</div>
<div class="row table-responsive " style="padding-left: 3%">
<input type="hidden" id="LookupId" />
<div id="datalist">
@(Html.Kendo().Grid<DHCS.BH.Provider.Models.LookupTable>()
.Name("LookupGrid")
.EnableCustomBinding(true)
.AutoBind(false)
.Columns(columns =>
{
columns.Bound(p => p.Id).Hidden();
columns.Bound(p => p.Type);
columns.Bound(p => p.Description);
columns.Command(command => { command.Custom("View").Click("ViewLookupTableValues").HtmlAttributes(new { @class = "k-primary" }); }).Width(100);
})
.Pageable()
.Sortable()
.Scrollable()
.Resizable(resize => resize.Columns(true))
.Filterable(x => x.Extra(false).Operators(O => O.ForString(str => str.Clear().StartsWith("Starts With"))))
.HtmlAttributes(new { style = "height:550px;" })
.DataSource(ds => ds
.Ajax()
.PageSize(20)
.Model(model => { model.Id(p => p.Id); })
.Read(read => read.Action("GetLookupValues", "Admin").Data("GetLookupTableValue"))
)
)
</div>
</div>
</div>
</div>
}
<pre>
$(document).ready(function ()
{<br />
var grid = $("#LookupGrid").data("kendoGrid");
grid.dataSource.read();<br />
})
function ViewLookupTableValues(e)
{
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
var PkContactId = dataItem.Id;
window.location.href = '@Url.Action("GetProgramTypeById", "ProgramType")?id=' + Id + "&Type=View";
}
function GetLookupTableValue(e)
{ return {
LookupTableId: $("#Lookup").kendoDropDownList().val()
}
}
</pre>
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
|
|
|
|
|
|
So I have it working where I can get the wwwroot from the controller, but I would like to be able to get it from a class static function that the controller calls.
I’m at the point where I have to decide whether to refactor my static class functions to pass the Environment, or search for a way to access it in the static functions, like for sending email and picking up a HTML template to populate.
This is sort of a dumb question, but is it possible to do?
Or should just rewrite my class functions and pass the Enviroment?
In addition, I need to get my settings in appsettings.json as well, in which I can access them in the view and controller, it not in a class, so the same question applies for that as well.
I’ve searched all over the Internet and It’s just examples of controller and view. On a side question, what’s with the binding options in configureServices in Startup.cs? I don’t have my computer in front of me to give better details about it.
Future Questions:
I just have a few more issues to go, and I should be able to complete my port over to core.
Cookies, core seems to use the single cookie value and not the cookie collection ; in which I posted a question on this earlier.
System.drawing Color, missing in that Nuget Package.
User-Agent
IpAddress
Server.MapPath - what is your work around?
A couple more
Warming;
Any typos or misspelling I will blame on my phone and not me.
I’m actually impressed with how well this works on my phone.
Job well done!
If it ain't broke don't fix it, I broke the rule on this.
Discover my world at jkirkerx.com
modified 29-Jun-18 2:30am.
|
|
|
|
|
Refactor the static methods and pass the IHostingEnvironment to them. Otherwise, they'll be impossible to test.
Similarly with the configuration: pass the IConfiguration (or the strongly-typed configuration object) to the methods.
Not sure what you mean by bindingOptions ?
Multi-value cookies were never standardized, so Core doesn't support them. There are various options for handling multiple values suggested in this StackOverflow thread[^] - the Cookie Manager project[^] looks promising.
Several suggestions for Core image processing libraries on the .NET blog: .NET Core Image Processing | .NET Blog[^]
User agent should be available with: Request.Headers[HeaderNames.UserAgent]
How to get user Browser name ( user-agent ) in Asp.net Core? - Stack Overflow[^]
IP address is available from HttpContext.Connection.RemoteIpAddress - inject the IHttpContextAccessor service to get the current context.
Get Client IP Address in ASP.NET Core 2.0 - Edi Wang[^]
Server.MapPath doesn't really apply any more, since Core doesn't support virtual directories. You just use IHostingEnvironment[^] to get the physical root path, and then Path.Combine[^] to build the path to a folder or file within that path.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Things re much clearer now, thanks!
You gave me the info I needed to push ahead now.
This is the binding thing in ConfigureServices. I was trying to get the Settings and Configuration direct from the static class function and added the 2nd call. The 3rd call was from another online source. I suspect the 2nd and 3rd calls are not needed, but I'll have to comment them out and see what happens to determine that.
services.Configure(Configuration.GetSection("Settings"));
services.Configure(options => Configuration.GetSection("Settings").Bind(options));
services.AddSingleton(Configuration);
As for System.Drawing, I'm using CoreCompat.System.Drawing which works so far, it just have Color, but has Bitmap and stuff like that.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
I have 2 issues here on replacing MapPath. After reading many articles on the subject, guess I am the sloppy programmer that used MapPath inside functions to handle physical file locations for image and html file reading and writing.
On the first issue, I seeded my database with data that includes blobs of image bytes and then wrote the bytes to the folder as an image. I'm seeding my database in Program.cs which works fine, it creates the database but I can't grasp the MapPath or Environment.
I noticed in CreateWebHostBulder , if I add .ConfigureAppConfiguration((hostingContext, config) => that I can access the enviroment, so I can pass it to SeedData.Intialize(services, environment); , but then I can't access the DBcontext. But in the code below, I can access the DBContext, but can't figure out how to access the environment.
To the best of my understanding, I'm injecting the environment in startup.cs, which runs after program.cs. I'm lead to believe that I can't use or Initialize the enviroment in the actual SeedData either, so I thought I could pass it along.
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{<br />
var context = services.GetRequiredService();
context.Database.Migrate();
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}
host.Run();
}
On issue 2, I just can't seem to understand how create a class for MapPath. I tried this, the code below, but I'm testing on the Database Seed function so I know it's not injected yet because it's injected in startup.cs, and not program.cs.
So I'm flying around in circles, and not really sure how to approach this.
public class ServerPath
{
private IHostingEnvironment _hostingEnvironment;
public ServerPath(IHostingEnvironment environment)
{
_hostingEnvironment = environment;
}
public string MapPath(string path)
{
string filePath = string.Empty;
try
{
filePath = Path.Combine(_hostingEnvironment.WebRootPath, path);
}
catch(Exception e)
{
Console.WriteLine(e.Message.ToString());
}
return filePath;
}
public string CombinePath(string path, string fileName)
{
string filePath = string.Empty;
try
{
filePath = Path.Combine(_hostingEnvironment.WebRootPath, path + "\" + fileName);
}
catch (Exception e)
{
Console.WriteLine(e.Message.ToString());
}
return filePath;
}
}
}
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Maybe just getting the current Directory and adding wwwroot to it is the way to go for seeding.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
The code in Startup runs as part of the BuildWebHost method in the Program class. That gets invoked both by the application, and by the design-time EF commands (add-migration , update-database , etc.), so you can't seed the data in the Startup class.
In 2.0 projects using EF Core 2.0, Program.BuildWebHost is invoked to obtain the application services. Unlike 1.x, this has the additional side effect of invoking Startup.Configure . If your 1.x app invoked database initialization code in its Configure method, unexpected problems can occur.
So the seeding code needs to be in Main , on in the context's OnModelCreating method[^].
In theory, you should be able to inject any registered service into your DbContext constructor, which would let you access your ServerPath service from the OnModelCreating method.
Alternatively, you can retrieve the services from the Main method using services.GetRequiredService<ServerPath>(); within the try block.
(Personally, I tend to keep the migrations and seed data in a separate console app, because I don't want the website connecting to SQL using an account that has permissions to create and modify databases.)
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hmm....
I'll leave the seed in Main for now, and make sure everything works before reconsidering a change.
But I changed the file paths from Url types to physical types with Path.Combine and I successfully seeded my database with the blobs and Url paths and wrote the images to the folders. Getting past System.Drawing yesterday was whole nother issue.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Last question of the day I hope.
I've been job hunting over the last 3 months. In my area there are all these Senior MVC Full Stack Developer job postings in which they ask for the following qualifications. I suspect it's all these different recruiting companies looking for one person in general, or someone considering leaving Silicon Valley and heading south.
MVC 5,
.Net Core
c#, VB
CSS, CSS3
HTML5
Javascript, JQuery
SQL Server, Stored Transactions
ORM, CRUD, Azure, Git, NodeJS
AngularJS 2-5
What I can't figure out is why the AngularJS with MVC. AngularJS seems to be a client side version of MVC. From what I have read, a crawler can't read an AngularJS page created 100% by AngularJS, so you have to use something that will download a static page first like MVC, then you can inject some AngularJS to say continue showing more cars.
I would think that ReactJS would be more suitable over AngularJS, being able to use the same server side controller and reducing code writing. Then say if the price of the car changes, the ReactJS polling will update that without a page refresh.
Last but not least, how the heck do these guys have the time to master all of these skills. Do these programmers really exist?
I didn't pickup Angular because I was busy learning Bootstrap 3 and 4, and writing responsive CSS.
I'm just trying to understand the posting, and would love to visit the job requester to see how they are using this and learn.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
You're querying the combination of angular and MVC, but not c# and vb.net?
You get all sorts of rubbish in jobs ads, they're just throwing lots of tech in to cast their net wide and get as many applicants as possible, hoping to maybe get someone who knows every technology out there in the process. You won't really need all of those things though. It's up to you to decide if you want to spend time dealing with people who post adverts like that, or if you want to deal with people who are a bit more focused in what they want.
|
|
|
|
|
Good Reply. Guess non programmers are composing these job postings and just throwing out rubbish.
Perhaps I'm suppose to call them on it, or play the game.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
jkirkerx wrote: AngularJS 2-5 To clarify, the team announced that separate terms should be used for each framework with "AngularJS" referring to the 1.X versions and "Angular" without the "JS" referring to versions 2 and up.
I'm amazed they're not asking for "8+ years experience with ASP.NET Core", given it was released back in 2016.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Didn't know that.
I had one recruiter call me and ask me questions about Angular. In the end I asked here why and she wasn't able to answer the question. Then I said your not a programmer are you and she replied no. They must copy and paste these job requirements and claim them as their own.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Well I have two functions called Startup and I just need one I think. One was stock called Startup(IConfiguration configuration) that gets called from Program.cs I think, and the other I added from examples in how to read the appsettings.json file called Startup(IHostingEnviroment env) and how to initialize the database.
So basically being so new here, I must of confused versions such as core 1 vs core 2
I would assume the first is correct.
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
And the 2nd one is incorrect for core 2.1
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
using (var client = new IndigoDBContext())
{
client.Database.EnsureCreated();
client.Database.Migrate();
}
Configuration = builder.Build();
}
But I don't see another place that has the environment except for Configure. Maybe the 2nd code goes there.
I'm trying to get my database created, and set migration.
Question is: I suspect I'm on the wrong track here, and I need a little help getting squared up on this. I probably have duplicates of or version overlaps here.
This is my ConfigureServices Function, I'm pretty sure I have this right
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
<pre>
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddApplicationPart(typeof(ErrorController).GetTypeInfo().Assembly);
services.AddHttpContextAccessor();
services.Configure<AppConfiguration>(Configuration.GetSection("AppConfiguration"));
services.Configure<SmtpConfig>(Configuration.GetSection("SmtpConnection"));
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddEntityFrameworkSqlite().AddDbContext<indigodbcontext>();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
services.AddHttpContextAccessor();
}
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|