Web Repository - Structure Analysis¶
Executive Summary¶
The Psyter Web Application is a comprehensive ASP.NET MVC 5 application serving as the primary web portal for the telemedicine platform. It implements a traditional three-tier architecture with MVC pattern, supports bilingual content (English/Arabic with RTL), and provides extensive functionality for multiple user roles.
Architecture Pattern: Model-View-Controller (MVC)
Framework: ASP.NET MVC 5.2.3 on .NET Framework 4.7.2
Lines of Code: ~60,000+ (estimated)
Primary Language: C# with Razor views, JavaScript
Architecture Overview¶
High-Level Architecture¶
┌─────────────────────────────────────────────────────────────┐
│ Client Browser │
│ (HTML/CSS/JavaScript - Bilingual EN/AR with RTL) │
└────────────┬────────────────────────────────────────────────┘
│ HTTPS
│
┌────────────▼────────────────────────────────────────────────┐
│ ASP.NET MVC Application │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Presentation Layer │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
│ │ │Controllers │ │ Views │ │ Filters │ │ │
│ │ │ (Action │ │ (Razor) │ │ (Auth/Role)│ │ │
│ │ │ Methods) │ │ │ │ │ │ │
│ │ └────────────┘ └────────────┘ └────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Business Logic Layer │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
│ │ │ Common │ │ Models │ │ Validators │ │ │
│ │ │ Utilities │ │ (DTOs) │ │ │ │ │
│ │ └────────────┘ └────────────┘ └────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Data Access Layer │ │
│ │ ┌────────────┐ ┌────────────┐ │ │
│ │ │ API │ │ DAL │ │ │
│ │ │ DataAccess│ │ Manager │ │ │
│ │ └────────────┘ └────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└────────────┬────────────────────────────────────────────────┘
│ HTTP/HTTPS API Calls
│
┌────────────▼────────────────────────────────────────────────┐
│ Backend APIs │
│ ├─ PsyterAPI (Main Backend) │
│ ├─ Media Upload API │
│ ├─ Scheduling API │
│ └─ Google Analytics API │
└─────────────────────────────────────────────────────────────┘
Application Layers¶
1. Presentation Layer¶
Controllers (/Controllers)
- Organization: Role-based and feature-based grouping
- Key Controllers:
- WebController - Public pages, home, about, FAQ
- UserManagerController - User authentication, registration
- ClientController - Patient-specific features
- ServiceProviderController - Care provider features
- Admin/CatalogueController - Admin catalog management
- AccountantController - Financial features
- CollaborationController - Collaboration features
- CommonController - Shared endpoints
Views (/Views)
- Organization: By role and language
- Structure:
Views/
├── Web/
│ ├── English/
│ └── Arabic/
├── Patient/
├── Physician/
├── Admin/
├── Shared/
│ ├── _Layout.cshtml
│ ├── _Layout_AR.cshtml
│ └── Partials/
Filters (/Filters)
- AuthenticateUser - Session-based authentication
- IsAdmin, IsClient, IsServiceProvider - Role-based authorization
- IsAccountant, IsMarkeetingManager, IsSeoManager, IsContentManager - Specialized roles
- exceptionFilter - Global exception handling
- CustomRouting - Custom route handling
2. Business Logic Layer¶
Common Utilities (/Common)
AppConstants.cs // Application-wide constants
APIAuthenticationToken.cs // API token management
Common.cs // Helper methods, SEO data, utilities
Models (/Models)
- Domain Models:
- UserProfile, PersonalInformation, ContactInformation
- Availability, Booking, Appointment
- Prescription, Scrc (clinical records)
- WorkExperience, EducationHistory, CvDetails
- GroupSessionViewModel, RefundPayment
- Request DTOs (
/Models/Request): UserRegistrationRequest,UserAuthRequestAvailabilityBookingRequestCatalogueRequest,FilterCriteria-
GoogleAnalyticsReportRequest -
Response DTOs (
/Models/Response): UserAuthResponse,UserRegistrationResponseServiceProviderResponse,AvailabilityResponseCatalogueResponse,CommonResponse-
APIAuthTokensResponse -
Catalog Models:
CatSpeciality,CatEducationType,CatPhysicianRole-
CatSalutation,CatUserPreference,CatScreeningQuestion -
Enums (
/Models/Enums): Enumeration.cs,Enum.cs- Application enumerations
Session Management (/Models)
- SessionVariables.cs - Session key constants
- UserLoginInfo.cs - User session data
- APIAuthToken.cs - API authentication tokens
3. Data Access Layer¶
API Communication (/DataAccess)
ApiDataAccess.cs
├── Constructor: Initializes HttpClient with base URL
├── Authentication Methods
│ ├── GetUserDetails(username, password)
│ └── Token management
├── User Management
│ ├── RegisterUser(UserRegistrationRequest)
│ ├── VerifyUser(verificationCode)
│ └── User CRUD operations
├── Catalog Methods
│ ├── GetPhysicianRoles()
│ ├── GetSpecialities()
│ ├── GetCountries()
│ └── Other catalog data
└── Generic Methods
├── GET requests
├── POST requests
└── File uploads
DALManager.cs
├── API type enumeration (Psyter, Scheduling, etc.)
├── Constructor: API-specific initialization
├── Generic Data Methods
│ ├── GetData(endpoint, method, token)
│ ├── PostData(data, endpoint, method, token)
│ ├── PutData(data, endpoint, method, token)
│ └── DeleteData(endpoint, method, token)
└── Error handling and logging
Component Breakdown¶
Controllers Structure¶
Controllers/
├── Admin/
│ └── Catalogue/
│ ├── CatalogueController.cs (1,200+ lines)
│ ├── ManagePromotionController.cs (350+ lines)
│ ├── PaymentController.cs (1,800+ lines)
│ ├── PhysicianListController.cs (600+ lines)
│ └── UserPreferenceController.cs (450+ lines)
├── Accountant/
│ └── AccountantController.cs (500+ lines)
├── Patient/
│ ├── ClientController.cs (2,500+ lines)
│ └── ScreeningController.cs (400+ lines)
├── Physician/
│ ├── ServiceProviderController.cs (3,700+ lines) ⚠️ Very large
│ ├── PhysicianAvailabilityController.cs (1,100+ lines)
│ └── PrescriptionController.cs (300+ lines)
├── CollaborationController.cs (250+ lines)
├── CommonController.cs (1,500+ lines)
├── ContentManagerController.cs (200+ lines)
├── ErrorController.cs (100+ lines)
├── EventController.cs (800+ lines)
├── MarkeetingController.cs (500+ lines)
├── OrganizationController.cs (400+ lines)
├── SEOManagerController.cs (300+ lines)
├── UserManagerController.cs (2,800+ lines)
├── UserPreferenceDataController.cs (200+ lines)
└── WebController.cs (900+ lines)
Views Organization¶
Public Views (/Views/Web)
- Home, About, FAQ, Contact
- Privacy Policy, Terms & Conditions
- Care Provider Listings
- Blog/Content pages
- Psychological Tests/Screening
Patient Views (/Views/Patient)
- Dashboard
- Profile management
- Appointment booking
- Session history
- Messaging
- Diary/Journal
- Homework
Care Provider Views (/Views/Physician)
- Dashboard
- Profile/CV management
- Schedule/Availability
- Patient management
- Appointment list
- Prescription creation
- Group session management
- Payslip/Financial reports
Admin Views (/Views/Admin)
- User management
- Catalog management
- Promotion management
- Reports
- Configuration
Shared Components (/Views/Shared)
- _Layout.cshtml - English layout
- _Layout_AR.cshtml - Arabic layout (RTL)
- Partial views for reusable components
- Error pages
Static Assets Organization¶
Stylesheets (/Content)
Content/
├── css/
│ ├── Arabic/ # RTL-specific styles
│ │ ├── bootstrap.min.css
│ │ ├── style-*.css
│ │ └── ui-date-picker-ar.css
│ ├── style-*.css # Feature-specific styles
│ ├── bootstrap.min.css
│ └── font-awesome.min.css
├── stylesheets/
│ ├── pages-stylesheets/ # Page-specific styles
│ │ ├── style-home-page.css
│ │ ├── style-appointment-page.css
│ │ └── ...
│ └── bootstrap*.css
├── fonts/ # Custom fonts
│ ├── Alexandria/ # Arabic font
│ ├── Lato/ # English font
│ └── webfonts/ # Font Awesome
├── images/ # Application images
│ ├── img/ # Organized images
│ ├── meeting/ # Video meeting icons
│ └── mobileappimages/ # Mobile app download
└── svgs/ # SVG icons
JavaScript (/Scripts)
Scripts/
├── JS/ # Custom JavaScript
│ ├── AdminManageOrganizations.js
│ ├── BookGroupSession.js
│ ├── ClientPackages.js
│ ├── join-meeting-conference.js
│ ├── join-meeting-guest.js
│ ├── ManageGroupSession.js
│ ├── OrganizationDashboard.js
│ ├── PayForReservedSlots.js
│ └── QuestionnaireHistory.js
├── sweat-alert/ # Alert library
├── jquery-*.js # jQuery library
└── Third-party libraries
Key Design Patterns¶
1. MVC Pattern¶
- Model: DTOs for API communication, view models
- View: Razor templates with bilingual support
- Controller: Orchestrates business logic, API calls
2. Repository Pattern (Implicit)¶
ApiDataAccessacts as repository for API operationsDALManagerprovides abstraction over different API types
3. Filter Pattern¶
- Custom action filters for authentication/authorization
- Exception handling filter
- Route handling filter
4. Session State Pattern¶
- User authentication via session
- API tokens cached in session
- User preferences in session
5. DTO Pattern¶
- Separate request/response models
- Clean API contract boundaries
- Type-safe data transfer
Data Flow¶
Typical Request Flow¶
1. Browser Request
├─> IIS/IIS Express
│
2. ASP.NET Pipeline
├─> Authentication Filter (Session validation)
├─> Authorization Filter (Role check)
├─> Controller Action
│ ├─> Session data retrieval
│ ├─> Build API request (DTO)
│ ├─> Call DALManager/ApiDataAccess
│ │ ├─> HTTP request to backend API
│ │ ├─> Deserialize JSON response
│ │ └─> Return response DTO
│ ├─> Process response data
│ ├─> Prepare View Model
│ └─> Return View Result
│
3. View Rendering
├─> Select language-specific view
├─> Render Razor template
├─> Apply layout (_Layout or _Layout_AR)
├─> Include CSS/JS bundles
└─> Generate HTML
│
4. Response to Browser
└─> HTML/JSON with security headers
API Communication Pattern¶
// Example: Getting user profile
public async Task<ActionResult> GetProfile()
{
// 1. Get session data
var userInfo = (UserLoginInfo)Session[SessionVariables.UserLoginInfo];
var apiTokens = (APIAuthTokensResponse)Session[SessionVariables.APIAuthTokenList];
// 2. Prepare API request
var dalManager = new DALManager(ApiType.psyter);
// 3. Call API
JObject response = await dalManager.GetData(
userInfo.UserID.ToString(),
PsyterApiMethodNames.UserProfile,
apiTokens.APIAuthToken.access_token
);
// 4. Deserialize response
var profileResponse = response.ToObject<UserProfileResponse>();
// 5. Return view with data
return View(profileResponse);
}
Configuration Management¶
Application Settings (Web.config)
<appSettings>
<!-- API Endpoints -->
<add key="PsyterApiBasePath" value="https://..." />
<!-- Application Token -->
<add key="PsyterApplicationToken" value="..." />
<!-- Session Configuration -->
<add key="SessionTimeoutCountDown" value="180" />
<!-- JSON Serialization -->
<add key="aspnet:MaxJsonDeserializerMembers" value="10000000"/>
</appSettings>
Security Configuration
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN" />
<add name="X-Xss-Protection" value="1; mode=block" />
<add name="X-Content-Type-Options" value="nosniff" />
<add name="Referrer-Policy" value="same-origin" />
<add name="Strict-Transport-Security" value="max-age=31536000" />
</customHeaders>
</httpProtocol>
</system.webServer>
Bilingual Support Architecture¶
Language Management
Session[SessionVariables.CurrentLanguage]
├─> "en" (English) or "ar" (Arabic)
│
View Selection
├─> ~/Views/[Area]/English/[View].cshtml
└─> ~/Views/[Area]/Arabic/[View].cshtml
CSS Selection
├─> /Content/css/style-*.css (LTR)
└─> /Content/css/Arabic/style-*-ar.css (RTL)
Layout Selection
├─> ~/Views/Shared/_Layout.cshtml (LTR)
└─> ~/Views/Shared/_Layout_AR.cshtml (RTL)
Implementation Example
public async Task<ActionResult> Home()
{
string viewPath = "";
if (Session[SessionVariables.CurrentLanguage].ToString() == AppConstants.Languages.English)
{
viewPath = "~/Views/Web/English/Home.cshtml";
}
else
{
viewPath = "~/Views/Web/Arabic/Home.cshtml";
}
return View(viewPath);
}
Authentication & Authorization Flow¶
User Request
│
▼
[AuthenticateUser Filter]
├─> Check Session[UserLoginInfo]
├─> If null → Redirect to Login
└─> If valid → Continue
│
▼
[Role-Based Filter] (IsClient, IsAdmin, etc.)
├─> Check Session[UserLoginInfo].RoleID
├─> If unauthorized → Redirect to Access Denied
└─> If authorized → Execute Action
│
▼
Controller Action
└─> Business Logic
Filter Implementation
public class IsClient : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var userInfo = (UserLoginInfo)HttpContext.Current.Session[SessionVariables.UserLoginInfo];
if (userInfo == null || userInfo.RoleID != (int)UserRoles.Client)
{
filterContext.Result = new RedirectResult("~/Error/AccessDenied");
}
}
}
Session Management¶
Session Variables (SessionVariables.cs)
- CurrentLanguage // "en" or "ar"
- UserLoginInfo // User authentication data
- APIAuthTokenList // API access tokens
- UserProfileInfo // Cached user profile
- SelectedCareProvider // Currently viewing provider
- BookingInfo // Appointment booking data
- PaymentInfo // Payment transaction data
Session Lifecycle
1. Session_Start - Initialize common data, get API tokens
2. During Request - Read/write session data
3. Session Timeout - Redirect to login (configured: 180 seconds)
Error Handling¶
Global Exception Filter
public class exceptionFilter : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
// Log exception
// Set error view
// Clear response
filterContext.ExceptionHandled = true;
}
}
Error Controller
ErrorController
├─> NotFound() - 404 errors
├─> AccessDenied() - 403 errors
└─> ServerError() - 500 errors
Performance Considerations¶
Bundling & Minification (BundleConfig.cs)
bundles.Add(new ScriptBundle("~/bundles/jquery")
.Include("~/Scripts/jquery-{version}.js"));
bundles.Add(new StyleBundle("~/Content/css")
.Include("~/Content/bootstrap.css", "~/Content/site.css"));
Caching Strategy
- Static content caching (CSS, JS, images)
- API token caching in session
- Application Insights for monitoring
External Integrations¶
-
Google Analytics
- Google.Analytics.Data.V1Beta package
- Analytics reporting features
- Custom event tracking -
Application Insights
- Microsoft.ApplicationInsights packages
- Performance monitoring
- Exception tracking
- Dependency tracking -
Payment Gateway
- Payment processing inPaymentController
- Merchant certificates (MerchantCertificates.p12) -
Video Conferencing
- Video session UI in/Content/images/meeting/
- WebRTC implementation (likely in JavaScript)
Technical Debt & Concerns¶
Code Organization Issues¶
-
Oversized Controllers ⚠️ Critical
-ServiceProviderController.cs- 3,700+ lines
-ClientController.cs- 2,500+ lines
-UserManagerController.cs- 2,800+ lines
- Should be split into smaller, focused controllers -
Mixed Responsibilities
- Controllers handling both UI and API logic
- Business logic in controllers instead of services
- Direct API calls from controllers -
Code Duplication
- Similar view selection logic across controllers
- Repeated session management code
- Duplicate API call patterns
Architectural Issues¶
-
No Service Layer
- Business logic directly in controllers
- API calls from controllers
- Difficult to test and maintain -
Tight Coupling
- Controllers tightly coupled to API structure
- Session dependency throughout application
- Hard-coded view paths -
Limited Abstraction
- Direct HttpClient usage
- No repository abstractions
- Limited dependency injection -
Session Overuse
- Heavy reliance on session state
- Scalability concerns
- State management complexity
Maintainability Concerns¶
-
View Duplication
- Separate English and Arabic views
- Difficult to maintain consistency
- Code duplication between languages -
Configuration Management
- Settings in Web.config
- No environment-specific configs
- Hard-coded values in code -
Error Handling
- Inconsistent error handling
- Generic exception catching
- Limited error logging
Recommendations¶
Immediate (Do Now)¶
-
Split Large Controllers
- Break downServiceProviderControllerinto feature-specific controllers
- Extract common functionality to base controllers
- Implement proper separation of concerns -
Implement Service Layer
- Create service classes for business logic
- Move API calls to service layer
- Improve testability -
Reduce Session Dependency
- Implement claims-based authentication
- Use dependency injection for user context
- Consider stateless authentication (JWT)
Short-term (Do Next)¶
-
Improve Localization
- Implement resource files for translations
- Share views between languages
- Use localization helpers -
Add Unit Tests
- Test business logic in services
- Test controllers with mocked dependencies
- Test API data access layer -
Implement Dependency Injection
- Use built-in DI container
- Inject services into controllers
- Improve testability
Long-term (Plan)¶
-
Modernize to .NET Core/6+
- Better performance
- Cross-platform support
- Modern framework features -
Implement CQRS Pattern
- Separate read and write models
- Improve scalability
- Better performance -
API Gateway Pattern
- Centralize API calls
- Better error handling
- Improved security
Document Version: 1.0
Last Updated: November 2025
Next Review: Quarterly