5 ms·
Same, but with ASP.NET (which produces an OpenAPI specification) + Entity Framework on the server, React + TypeScript on the client (which consume that specific
by 5e92cb50239222b 4y ago
Same, but with ASP.NET (which produces an OpenAPI specification) + Entity Framework on the server, React + TypeScript on the client (which consume that specification through openapi-generator).
https://github.com/OpenAPITools/openapi-generator https://github.com/OpenAPITools/openapi-generator
I chuckle every time I read claims about Go (or whatever) being amazingly productive. I don't think it's possible to beat this stack with regards to both productivity and ease of long-term support, at least without going to very niche technologies where you'll have other problems.
Database schema is generated from models described in C# (or reverse-engineered from an existing schema). You don't have to compromise your schema to satisfy the ORM (another claim I often read on HN), as it's very adaptable to your needs.
Migrations are generated automatically — change your models, ask it to generate migration code in C# + a SQL migration script, review the generated SQL, and apply.
The vast majority of database queries (pretty much everything besides reports) is written in type-safe LINQ, which makes it easy to refactor code, and also construct & combine queries at runtime. Unlike that specification abomination JPA expects you to use, LINQ queries look something like this:
var latestOrders = _db.Orders
.Where(ord => ord.CreatedAt >= DateTime.Today)
.Where(ord => !ord.Deleted)
.OrderByDescending(ord => ord.CreatedAt)
.Take(25)
.Select(ord => new {
OrderId = ord.Id,
Customer = ord.Customer.Name,
CreatedAt = ord.CreatedAt,
Products = ord.Products.Select(prod => new {
ProductId = prod.Id,
Title = prod.Title,
})
})
.ToList();
If you change your schema and forget to update one of the queries accordingly (although using an IDE makes this pretty much impossible), your code won't even compile.
- jakub_jo 4y agoThat sounds impressive.
- melony 4y agoDo you still need to pass around "Data Transfer Objects" to do simple parameter binding?
- jeremycarter 4y agoThey form the type safety
- pevey 4y agoThis is very backend-centric. It can't compare to a framework like SvelteKit or NEXT or NUXT, where the primary benefit is also shipping your tightly-integrated frontend code to the browser. .NET apps are old school, full refresh apps unless you are also using a separate frontend framework like React or Vue standalone. And that adds a lot of time and overheard. Everything you described in terms of easy migrations and querying is exactly what Prisma gives you in the stack the OP described.
- stetrain 4y agoThey are describing using .NET as an API providing a typed OpenAPI contract (aka swagger). Nothing about that is “full refresh” and you can use whichever frontend framework you like.
- arcturus17 4y ago> .NET apps are old school Microsoft has invested massively in modernizing .NET and C#. It is also widely praised by devs - .NET is ranked 4th most loved framework in the SO 2022 dev survey. You have built-in scaffolding to get a React + .NET app right from the CLI, with hot-reload and all the facilities you'd expect. Hardly old school at all. Personally, if I had to build a website with a thin API layer I'd reach for NextJS (or equivalent) alone, but anything beyond that I'd go for .NET Core any time of day.
- brushfoot 4y agoExactly. With ASP.NET, a React/Angular project is separate, there's a separate model layer, and you have to keep that in sync with the .NET models. With Next, there's true code reuse between client and server. Next is smart about shipping your code where it needs to run, server, client, both. You can even mix and match from page to page: Server-side render one page per request; statically generate another at build time. As much as I like ASP.NET, Next has leapfrogged it for web apps.
- arcturus17 4y ago> As much as I like ASP.NET, Next has leapfrogged it for web apps. Look, I like NextJS as much as the next guy - I'd say it's my main working technology right now. And I've never built anything on .Net - I know its characteristics from watching tutorials and reading docs. My take however is that "web apps" is a very broad world. NextJS gives you a thin API layer. There is no model layer to speak of. You're left fending for yourself in the wild, wild world of JavaScript. .Net Core, on the other hand, offers a batteries-included, heavy-lifting, opinionated framework, with an immense toolbox and many conventions to guide you. There has to be a reason why people speak such wonders of it. If I had to build something enterprise-y with more than handful of devs it would probably be my choice.
- NDizzle 4y agoCould you go into a little bit more detail?
- d0100 4y ago> I chuckle every time I read claims about Go (or whatever) being amazingly productive You can get the same'ish with Ent and Atlas I am very slowly building a big glue between DB and front-end and making it pluggable into their underlying libs and native libs
- lmm 4y ago> Database schema is generated from models described in C# (or reverse-engineered from an existing schema). You don't have to compromise your schema to satisfy the ORM (another claim I often read on HN), as it's very adaptable to your needs. Generating the schema from the models is easy mode, the ORM naturally won't generate anything it doesn't understand. The claim is that the ORM can't handle advanced schema features that it wouldn't generate. (Although in my experience most people claiming that just never bothered to learn the ORM).
- thdrtnl 4y agoIf your are going to mention .NET in this context, why not mention Blazor? With Blazor you just write both the reactive frontend and backend in C#. No need to write Javascript. Super productive, type safe all the way. Today it has even support for hot reloading. Save your C# and see the changes in your browser. https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blaz...
- Xevi 4y agoLast time I looked at Blazor it only had two options, which were both equally horrible for public websites. You either had to ship a big and bloated WASM file, which was at least 10x the size of competing JS frameworks, and in some cases 100X the size. Or you had to render all dynamic parts of your website on the server, which made latency a huge problem, since your website feels sluggish between each interaction.
- thdrtnl 4y agoI don't know when it was the last time you took a look at Blazor, but Blazer server is extremely fast. I built some big corporate apps with it and never had any latency problems.
- Xevi 4y agoWere they internal or external apps? Because latency was the problem last time I looked, and it won't be super noticeable if you have the servers that close to you.
- FridgeSeal 4y agoBecause last time I looked, the Blazor binaries were huge, and had performance issues? It's also irrevocably attached to that specific dotnet framework? Want to evolve parts of your stack? Too bad.
- DimmieMan 4y ago* The payload of WASM makes it a difficult choice if serving mobile or regions with poor internet and you want a good first impression. * Server side needing a constant socket for everything presents it's own limitations. * It has hot reloading, but it pales in comparison to the JS experience at best and in my own experience has a lot of edge cases leading to full rebuilds. * C# tooling is fantastic; Razor however I've found to be slow and well behind the experience of popular JS libraries. * When you do need JS interop (e.g. browser API's) the experience is, IMO, awful. I feel Blazor's niche is internal, simple LOB apps and I can understand the appeal if you don't already know JS or have some serious regulatory requirements around vendors and need to avoid NPM. Personally, I find the DX and quality of the end product in svelte kit trump the code sharing of Blazor.
- bottlepalm 4y agoFor local development do you run two servers, next and asp and then for dynamic api calls by the client do you proxy the request through next or go directly to the asp server by its port number? Similarly in production do you use a reverse proxy for the asp server so that requests to like /api go to the asp server?
- oh-4-fucks-sake 4y agoI agree with the sentiment--and with most of your comment--except the assertion that "I don't think it's possible to beat this stack". I have something similar: Kotlin on the server-side with my SQL DSL generated by jOOQ and Flyway running my schema migrations. I don't have any experience with LINQ--but it looks to be of a similar idea to jOOQ such that you get an autogenerated, injection-safe, type-safe, compile-time-checked SQL DSL. If you like LINQ, you'd probably really like jOOQ. It's uber-powerful and the only queries that I've not been able to completely write in jOOQ are geo-spatial queries--and even for them, I can use string SQL for just the one where-clause predicate where I need to go off-the-rails--the rest of the query still being standard jOOQ. The thing I like most about it, is that the queries that I write in the DSL are sooo close-to-the-metal of pure SQL--I'm not even context-switching between SQL and jOOQ really. Check it out!
- jcookeak 4y agoAlso have to sing praise for Kotlin, flyway, and some type-safe db framework. I’ve recently been migrating projects from jOOQ to SQLDelight. While not as feature complete, being able to write queries in sql and then generate type safe code has been amazing. My biggest issue with jOOQ has been joins where you lose some null safety and general issues with the generated POJO (which admittedly has improved over time). With SQLDelight, it has felt like the database just fades away when writing Kotlin.
- sonicgear1 4y agojOOQ is not even close to EF LINQ, I worked with both.
- kaba0 4y agoI think parent meant “stack” for every similarly high level, statically typed language. I can vouch for Spring (Data) with JPA. The criteria api is also very great.
- mythz 4y ago> I chuckle every time I read claims about Go (or whatever) being amazingly productive. I don't think it's possible to beat this stack with regards to both productivity and ease of long-term support It's easy to beat Open API, it adds friction, generates ugly code and has a suboptimal UI. If you use https://servicestack.net https://servicestack.net you don't to rely on an intermediary external tool, you can generate clean TypeScript DTOs directly from strong C# typed models, that only needs to generate the clean DTOs for your typed APIs (i.e. without the ugly client proxy) as all generated DTOs can be used with the smart generic Service Client, which works the same way across 9 popular languages [2], maximizing reusability and reducing any porting efforts if needing to support Mobile Apps in future. It works even better in .NET languages where if you properly design your Service Layer [3] into a impl-free project you can avoid code-gen entirely and share the DTOs that define your typed Service Contract with .NET clients enabling an end-to-end Typed API without code-gen, which dramatically improves Dev UX in C# clients like Blazor [4] since you can add/modify APIs whilst your Service is running. We also maintain a better integrated and UX Friendly API Explorer [5] that Open API's Swagger UI which generates richer, validation bound customizable Forms directly from your Typed DTOs, better discovery and API docs and a "Code" tab which gives API consumers step-by-step instructions for how to easily call your Typed APIs in their preferred programming language [6]. As for productivity I'd say it's hard to beat the productivity of AutoQuery [7] where you only need to define your API's typed POCO contract, which ServiceStack uses to implement fully queryable APIs, that you can access immediately from an instant build-in UI https://locode.dev https://locode.dev or rapidly create custom Blazor pages with Auto Form and AutoQueryGrid components [8]. [1] https://docs.servicestack.net/typescript-add-servicestack-reference https://docs.servicestack.net/typescript-add-servicestack-re... [2] https://servicestack.net/service-reference https://servicestack.net/service-reference [3] https://docs.servicestack.net/service-complexity-and-dto-roles https://docs.servicestack.net/service-complexity-and-dto-rol... [4] https://servicestack.net/blazor https://servicestack.net/blazor [5] https://docs.servicestack.net/api-explorer https://docs.servicestack.net/api-explorer [6] https://docs.servicestack.net/api-explorer#code-tab https://docs.servicestack.net/api-explorer#code-tab [7] https://docs.servicestack.net/autoquery https://docs.servicestack.net/autoquery [8] https://servicestack.net/blazor#auto-forms https://servicestack.net/blazor#auto-forms
- 4y ago
- jamra 4y agoAdd a `String.Equals(thing, thing2, StringComparison.OrdinalIgnoreCase)` in your where clause and now you're full table scanning. LINQ makes things easy, but has traps.
- lakomen 4y agoI generate backend and frontend types in 2 seconds with Go, after I define the model structs. I laugh at your slow running, resource wasting .net