I'm working on an ASP.NET project where I need to split our current application into a Canada/USA/International System. This split will allow certain users to only view/modify the Data in Regions that they have permission for.
To avoid a maintenance nightmare in the future I've added a RegionID to the main tables of the application, including permissions. This should allow me to easily split everything up, and manage what people are allowed to see and what people aren't allowed to see. Based on the AD user, I can then save their default region which will save them hassle of seeing a Region Splash screen every time they try to access the application.
As I've never built a regional web application, this sounds fairly simple in my head, but before I dive completely in I was wondering if there is a "by the book" way to do this? Keeping in mind that I would rather not have to completely re-build this app as I do not have the time or resources to do so.
in my opinion the best way to achieve this is using the same kind of approach as when you have different languages or countries. probably you will need to develop a file defining the context of the user, languagecontext, countrycontext - region in your case -. You can achieve this using database persistence with an ID for each region in user - anonymous is ok too - profile table or using cookies to save details of regioncontext. then you can consume that information in your normal classes displaying information taking into consideration user region.
public Region RegionContext
{
get
{
if (this.user != null &&
this.user.Region!= null)
return this.user.Region;
var region= _region.GetAllRegions().FirstOrDefault();
return region;
}
set
{
if (this.user == null)
return;
this.user.region = value;
_user.UpdateUser(this.User);
}
}
where region has the ID and user has a fk to region.
brgds!
Related
I'm relatively new to web development in my current role and we have an MVC SPA type application I'm developing with my team. I can't really share any code directly as it's all the property of my company, so generally:
We're currently working to make a wizard that will collect several points of data and combine it all into the backend's SQL Stored Procs for inserting into tables. To start we've built a viewmodel that injects in and displays the possible options for various fields / drop downs. As choices are made in the drop downs it draws in new layers of the wizard.
To keep track of everything selected, I feel like our current strategy might be suboptimal - or more complex than needed.
When the View is interacted with, we're serializing the #Model into json, pushing it into the controller along with any data gathered from the user, de-serializing it into the ViewModel type, and sending it back in to the new partial view - storing any modifications from that action.
This keeps track of the changes as the user works through the wizard and allows us to redraw the primary div/page space to get new information as the context of what we're asking for changes.
I've seen websites do this with Forms or other things like modal pop ups, but as this is a multi step conditional wizard I chose against using that pathway as the views quickly became a mess of conditional razor checks and in page updates.
I know enough to know I'm not sure what best practices are in web development and I'm finding it difficult to extrapolate from various tutorials around the web into the complexity of this particular project.
I can give a generified example of code below, but hopefully the explanation above will trigger someone's brain to help short cut me to a cleaner way to do this.
public class XController : Controller
{
...
public XController(XRepository xRepository, IViewModelFactory viewModelFactory, Input input)
{
_xRepository = xRepository;
_viewModelFactory = viewModelFactory;
_input = input;
}
public IActionResult XIndex()
{
return PartialView(); //Draws an add/edit/delete set of buttons to begin the wizard. Assume the Add button is clicked leading to the next method.
}
public IActionResult DisplayAddJob()
{
//get list of task and connection types so user can select
_taskTypes = _xRepository.GetTaskTypes().ToList();
_connectionTypes = _xRepository.GetConnectionTypes().ToList();
_queryTypes = _xRepository.GetQueryTypes().ToList();
//build and return viewmodel so u can bind it to AddjobIndex dropdowns
XViewModel xvm = _viewModelFactory.Build(User.Identity, _taskTypes, _connectionTypes,_queryTypes, "Miscellaneous", _input.Test);=
return PartialView(xvm); //The initial view model creation / draw happens here
}
[ActionName("JobQueryWithPriorData")]
public IActionResult JobQuery(string vConnection, string vmJson)
{
xConnection vc = JsonConvert.DeserializeObject<xConnection>();
xViewModel xvm = JsonConvert.DeserializeObject<xViewModel>(vmJson);
xvm.SelectedConnectionId = (int)vc.ConnectionId; //we equip the view model with data that changed in the page interaction
return PartialView("~/Views/Miscellaneous/X/JobQuery.cshtml", xvm); //redraw the view in the main content pane with the updates.
}
...
}
This pattern exists all across the controller. An example of the .cshtml code #razor / javascript calls into the Controller are as follows:
Razor:
<td class="td-main-table" valign="middle">
<button type="button" class="y" onclick="SelectButtonClicked('#JsonConvert.SerializeObject(Model.ConnectionList.Where(x=>x.ConnectionId == ct.ConnectionId))','#JsonConvert.SerializeObject(Model)')">
</button>
</td>
Javascript:
function SelectButtonClicked(vConnection, viewmodeljson)
{
var functionalUrl = '/X/QueryToTableWithPriorData'
$.ajax({
url: functionalUrl,
type: 'POST',
data: {
vConnection:vConnection,
vmJson:viewmodeljson
},
success:
function (response) {
$('#displayDataPartialView').html(response);
}
});
}
This methodology is working. We're slowly, over the life of the wizard, able to grab the users selections and keep track of them. I'm just curious if there is a better way to do this, as I'm certain if there is I'm not aware of where to hunt for it. I believe in the old days people would just store stuff in ViewData objects, but I didn't really start web dev until .net core 2.1.
My team and I have full creative control over this application, it's internal and something I built from the ground up specifically for our team to put internal tools into, it's fairly lightweight currently and I'm willing to modify it to have a better foundation going forward.
Would it be better to store the user selections in a table tied to the users session and just recall the data at the end of the wizard on submit?
Are forms more flexible than I think they are?
Should I use modal windows instead of redrawing the page every time as a step through this?
Edit:
After a few days of research, while I'm not sure I have the best practices by any stretch, I do believe what we're doing is adequate. I've learned more about client vs server-side rendering and I believe my post came from not quite understanding the two well enough.
I believe the functionality I was expecting was "client-side" functionality from a very server side framework: the ability to step through a wizard's various forms without losing the data as the client goes through. This can be achieved with javascript/angular/react/blazor manipulating the view without going back to the server with a post/get.
In the world where I'm using minimal javascript, the strategy I'm using to turn the model into json in order to attach more data to it on the server side and resend it to the client for further modification SEEMS appropriate.
I still am interested to see if anyone has a best practice, so I'll leave the question open for a bit longer to see if anyone has anything. It's possible I should add a more client side layer to the solution as currently my thought was to try and maximize how much I leveraged the C# portion of web development. It seems like that might be my overall issue here.
Additionally, I spent some time looking into ViewComponents at a the suggestion of a commenter, Xinran. They are neat and do perform similarly to the PartialView methodology I'm using. I like how they work, but they produce the same exact scenario. They are mostly server-side tools, and I still, in the end, run into exactly the scenario that makes me wonder if this is the best way to handle a wizard with multiple steps that evolves off the user's previous choices.
I am new to DDD, and I am trying to figure out a way to update aggregate by using a PUT verb.
If all properties in the aggregate have private setters, then it's obvious I need to have set of functionality for every business requirement. For an example
supportTicket.Resolve();
It's clear for me that I can achieve this with an endpoint such as /api/tickets/5/resolve, but what if i want to provide a way to update whole ticket atomically?
As an example, user can make a PUT request to /api/tickets/5 with a following body
{"status" : "RESOLVED", "Title":"Some crazy title"}
Do I need to do something like this in the ApplicationSercvice
if(DTO.Status != null && dto.Status == "RESOLVED")
supportTicket.Resolve();
if(DTO.Title != null)
supportTicket.setNewTitle(DTO.title);
If that's the case and changing ticket title has some business logic to prevent changing it if the ticket is resolved, should I consider some kind of prioritizing when updating aggregate, or I am looking at this entirely wrong?
Domain Driven Design for RESTful Systems -- Jim Webber
what if i want to provide a way to update whole ticket atomically?
If you want to update the whole ticket atomically, ditch aggregates; aggregates are the wrong tool in your box if what you really want is a key value store with CRUD semantics.
Aggregates only make sense when their are business rules for the domain to enforce. Don't build a tractor when all you need is a shovel.
As an example, user can make a PUT request to /api/tickets/5
That's going to make a mess. In a CRUD implementation, replacing the current state of a resource by sending it a representation of a new state is appropriate. But that doesn't really fit for aggregates at all, because the state of the aggregate is not under the control of you, the client/publisher.
The more appropriate idiom is to publish a message onto a bus, which when handled by the domain will have the side effect of achieving the changes you want.
PUT /api/tickets/5/messages/{messageId}
NOW your application service looks at the message, and sends commands to the aggregate
if(DTO.Status != null && dto.Status == "RESOLVED")
supportTicket.Resolve();
if(DTO.Title != null)
supportTicket.setNewTitle(DTO.title);
This is OK, but in practice its much more common to make the message explicit about what is to be done.
{ "messageType" : "ResolveWithNewTitle"
, "status" : "RESOLVED"
, "Title":"Some crazy title"
}
or even...
[
{ "messageType" : "ChangeTitle"
, "Title" : "Some crazy title"
}
, { "messageType" : "ResolveTicket"
}
]
Basically, you want to give the app enough context that it can do real message validation.
let's say I had aggregates which encapsulated needed business logic, but besides that there is a new demand for atomic update functionality and I am trying to understand a best way to deal with this.
So the right way to deal with this is first to deal with it on the domain level -- sit down with your domain experts, make sure that everybody understands the requirement and how to express it in the ubiquitous language, etc.
Implement any new methods that you need in the aggregate root.
Once you have the use case correctly supported in the domain, then you can start worrying about your resources following the previous pattern - the resource just takes the incoming request, and invokes the appropriate commands.
Is changing the Title a requirement of Resolving a ticket? If not, they should not be the same action in DDD. You wouldn't want to not resolve the ticket if the new name was invalid, and you wouldn't want to not change the name if the ticket was not resolvable.
Make 2 calls to perform the 2 separate actions. This also allows for flexibility such as, the Title can be changed immediately, but perhaps "resolving" the ticket will kick off some complex and time consuming (asyncronous) work flow before the ticket is actually resolved. Perhaps it needs to have a manager sign off? You don't want the call to change "title" tied up in that mix.
If needs be, create something to orchestrate multiple commands as per #VoiceOfUnreason's comment.
Wherever possible, keep things separate, and code to use cases as opposed to minimizing interacitons with entities.
You're probably right. But it's probably wiser to encapsulate such logic inside the ticket it self, by making a "change()" method, receiving a changeCommandModel (or something like this), so you can define the business rules inside your domain object.
if (DTO.Status != null && dto.Status == "RESOLVED")
supportTicket.Resolve(DTO.title);
I will change the underlying method to take title as parameter, this clarify the resolve action. That second if and validation you want in the domain method. It's really preference, more importantly is the message and I agree with #VoiceOfUnreason second option.
I’m starting to develop a ASP NET MVC 3 application and I have sought to follow some good DDD pratices. I have the following situation which would like an opinion.
One of the System features is the creation of activities which one or more users of the system will participate, a meeting for example. Any user with a certain access profile can create new activities, perhaps only the user who create an activity can change her. The question is:
What’s the correct place to insert this rule?
-> In every setter of “Activity” entity? Seems break the DRY.
-> In the repository at the moment of saving the changes? In this case , what would be the correct moment to pass the user permissions?
One more parameter to this method? In the class constructor(In my model, the repositories are interfaces, if I adopt this option,
the dependency would be explicit only in the infrastructure layer where the repositories are implemented?)
-> Controller? It seems to collaborate with an anemic model.
By the way, questions abound... What do you think about?
If you are using ASP.NET Membership you can take advantage of the Roles and Profile providers and use Authorize attributes to restrict access to the actual views where creation or editing occur. For example, the create action could be:
[Authorize(Roles="Activity Admin")]
public ActionResult CreateActivity()
{
return View();
}
Where "Activity Admin" is your creator role. Then your edit could look something like this:
[Authorize(Roles="Activity Admin")]
public ActionResult EditActivity(int id)
{
Activity activity = ActivityRepository.GetActivityByID(id);
if (activity.CreatorID != CurrentUser.ID)
{
return RedirectToAction("Activities");
}
return View(activity);
}
That if statement does the check to make sure the current logged-in user was the user who actually created the activity. The CurrentUser.UserID can be replaced with whatever method you use to retrieve the current logged-in user's unique ID. I usually use the ProfileBase class to implement a class that allows me to track the current user's info. The link below to another SO question shows how you can do that.
How can i use Profilebase class?
What can I do to avoid the repeated loading of static data every time a page is loaded in ASP.NET MVC2? This is pretty wasteful, and I would like to fix it.
My master page has the typical User Name + Company Name display in the top right corner. But because of the stateless nature of MVC, this data has to be looked up every single time a page is loaded, even though it never changes.
In the old webforms days I would just throw it into Session, but that seems to be discouraged in MVC. Plus the web app runs on a webfarm, so I really do not want to use session.
The web app already has quite a few static data items that get queried on every page load (user currency, user tax rate, etc), so I think a performance gain can be made by loading them only once at login time. I'm just not sure what the correct MVC method is (I am still quite new to MVC).
I always use the built-in ASP.NET cache for this, set the expiry appropriately and you're good to go.
public void Blah()
{
var company = HttpRuntime.Cache.Get("Company") as string;
if (company == null)
{
company = FetchCompanyFromDb();
HttpRuntime.Cache["Company"] = company;
}
return this.View(company);
}
Also see this previous question:
Caching in asp.net-mvc
Could you maybe encapsulate your User currency / User name / Tax etc into a user control and then use Output Caching on that?
Imagine some kind of a banking application, with a screen to create accounts. Each Account has a Currency and a Bank as a property, Currency being a separate class, as well as Bank. The code might look something like this:
public class Account
{
public Currency Currency { get; set; }
public Bank Bank { get; set; }
}
public class Currency
{
public string Code { get; set; }
public string Name { get; set; }
}
public class Bank
{
public string Name { get; set; }
public string Country { get; set; }
}
According to the REST design principles, each resource in the application should have its own service, and each service should have methods that map nicely to the HTTP verbs. So in our case, we have an AccountService, CurrencyService and BankService.
In the screen for creating an account, we have some UI to select the bank from a list of banks, and to select a currency from a list of currencies. Imagine it is a web application, and those lists are dropdowns. This means that one dropdown is populated from the CurrencyService and one from the BankService. What this means is that when we open the screen for creating an account, we need to make two service calls to two different services. If that screen is not by itself on a page, there might be more service calls from the same page, impacting the performance. Is this normal in such an application? If not, how can it be avoided? How can the design be modified without going away from REST?
It's an architectural decision that you should base on the size and complexity of your system. The more large/complex your system is, the more it's likely to benefit from increasing levels of separation/encapsulation (for example, you may find that BankService needs to scale more aggressively than CurrencyService, and running these services separately will allow you to do that).
What I would point out in response to your question, though, is that you should be considering caching the results of these service calls and reusing the result, rather than re-calling the service for every page load. If (as the names would suggest) the result of CurrencyService and BankService are not likely to change very often, you could cache them for minutes or hours at a time and not have to repeatedly make those calls.
If your application is busy (that is, if you think in terms of hits-per-second rather than hits-per-hour) then this can save you memory at runtime since the result of a single service call is shared between multiple page requests (rather than each page needing to get the result set separately).
it is normal and can not be avoided...
...unless you create a specific service that returns all the data for a specific screen in one run.
This is one of the negatives of the REST approach - basically if you deal with object queries, and you need lists of x objects, then you have x calls. Point.
Which means REST designs have limited scalabilit on that level.
Again, as in the start - you can always have a specific service returning all data you need on a complex form in one call.
Hang on, ReST is about representing resources.
I don't think you should be too strict on the following:
According to the REST design principles, each resource in the application should have its own service, and each service should have methods that map nicely to the HTTP verbs.
It should be perfectly fine that the resource your representing in the browser is a "form" and contains all the relevant information.
Just think about the right degree of abstraction when defining your URL structure.
Slavo,
there is no need to provide different services for different resources. In general, you should simply provide the views that help your clients achieve their goals. If one of such views is an integrated 'big' view (resource) including all the banks and currencies then that is fine. You still can provide fine grained views (resources) for authoring and editing banks and currencies.
If the banks and currencies happen to be provided by different Web applications and you need the client to resolve the references, then keep in mind that HTML pages do this all the time with inline images. Caching goes a long way to reduce the number of network calls in such scenarios (and the list of banks and currencies seem not to be very volatile).
(See http://www.nordsc.com/blog/?p=152 )
Example:
GET /service/account-management
200 Ok
Content-Type: application/vnd.my.accounting
<page>
...
<banklist href="http://other.org/service/banklist" type="application/atom+xml" />
<currencylist href="http://standard.org/currencies" type="application/rss+xml" />
...
</page>
The sub requests to banklist and currencylist should be served from the client's private cache most of the times.
Jan